home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 31 / Amiga Format CD31 (1998-09-02)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1998-10].iso / -seriously_amiga- / sound / ahi / developer / paula / paula_audio.a < prev    next >
Text File  |  1998-07-16  |  117KB  |  5,304 lines

  1. *** ScR ***
  2.  
  3. * $Id: paula_audio.a,v 4.20 1998/06/28 09:26:04 lcs Exp lcs $
  4. * $Log: paula_audio.a,v $
  5. * Revision 4.20  1998/06/28 09:26:04  lcs
  6. * The low pass filter state is now restored when the audio is deallocated.
  7. *
  8. * Revision 4.19  1998/02/16 02:38:15  lcs
  9. * Recording didn't work in all modes!
  10. *
  11. * Revision 4.18  1998/02/09 00:41:36  lcs
  12. * Fixed a interrupt problem (playback could touch record's enable bits!).
  13. *
  14. * Revision 4.17  1998/01/10 19:47:33  lcs
  15. * Alright, the DMA version is ready for release.
  16. *
  17. * Revision 4.16  1997/12/02 09:28:28  lcs
  18. * Fixed all known problems in the DMA mode.
  19. *
  20. * Revision 4.15  1997/12/02 09:27:33  lcs
  21. * Added a DMA mode (beta).
  22. *
  23. * Revision 4.14  1997/12/02 09:26:03  lcs
  24. * Enclosed FindTask("Picasso96") with Forbid()/Permit(), in order to
  25. *     silence PatchWork.
  26. *
  27. * Revision 4.13  1997/12/02 09:24:16  lcs
  28. * Rewrote the conversion routines, they should be faster now?
  29. * Added the AHIpaulaBufferLength environment variable.
  30. * There were errors in the new conversion routines, when the tempo changed.
  31. * 8 bit modes now have hardware volume control.
  32. * Added the AHIpaulaSwapChannels environment variable.
  33. * AHIsub_GetAttr() is much faster now.
  34. *
  35. * Revision 4.10  1997/12/02 09:22:37  lcs
  36. * Initial RCS'ed version.
  37. *
  38.  
  39. *** NOTES ***
  40.  
  41. *  The sampler routines are just for fun. Since interrupts must not be disabled,
  42. * there are lots of clicks.
  43.  
  44. ;------------
  45.  
  46.     include    version.i
  47.  
  48. VSTRING    MACRO
  49.         VERS
  50.         dc.b    " ("
  51.         DATE
  52.         dc.b    ")",13,10,0
  53.     ENDM
  54. VERSTAG    MACRO
  55.         dc.b    0,"$VER: "
  56.         VERS
  57.         dc.b    " ("
  58.         DATE
  59.         dc.b    ")",0
  60.     ENDM
  61.  
  62.     incdir    include:
  63.  
  64.     include    hardware/all.i
  65.  
  66.     include    devices/audio.i
  67.     include    devices/timer.i
  68.     include    dos/dos.i
  69.     include    exec/exec.i
  70.     include    graphics/gfxbase.i
  71.     include intuition/intuitionbase.i
  72.     include intuition/screens.i
  73.     include    resources/misc.i
  74.     include    resources/card.i
  75.     include    utility/utility.i
  76.     include    utility/hooks.i
  77.  
  78.     include    lvo/cardres_lib.i
  79.     include    lvo/dos_lib.i
  80.     include    lvo/exec_lib.i
  81.     include    lvo/graphics_lib.i
  82.     include    lvo/intuition_lib.i
  83.     include    lvo/timer_lib.i
  84.     include    lvo/utility_lib.i
  85.  
  86.     include    devices/ahi.i
  87.     include    libraries/ahi_sub.i
  88.     include    lvo/ahi_sub_lib.i
  89.  
  90.     include    macros.i
  91.  
  92. DEBUG_DETAIL    SET    0
  93.  
  94. _ciaa        EQU    $bfe001
  95. _ciab        EQU    $bfd000
  96.  
  97. AUD0        EQU    $0A0
  98. AUD1        EQU    $0B0
  99. AUD2        EQU    $0C0
  100. AUD3        EQU    $0D0
  101. AUDLC        EQU    0
  102. AUDLEN        EQU    4
  103. AUDPER        EQU    6
  104. AUDVOL        EQU    8
  105. AUDPERVOL    EQU    6
  106.  
  107. INTF_AUDIO    EQU    INTF_AUD3|INTF_AUD2|INTF_AUD1|INTF_AUD0
  108.  
  109. PALFREQ        EQU    3546895
  110. NTSCFREQ    EQU    3579545
  111. MINPER        EQU    62
  112.  
  113.  
  114. DMABUFFSAMPLES    EQU    512    ; 8 of these will be allocated!
  115. RECORDSAMPLES    EQU    1024
  116.  
  117.  
  118. * paula.audio extra tags
  119. AHIDB_Paula14Bit    EQU    AHIDB_UserBase+0    * Boolean
  120. AHIDB_PaulaTable    EQU    AHIDB_UserBase+1    * Boolean
  121. AHIDB_PaulaDMA        EQU    AHIDB_UserBase+2    * Boolean
  122.  
  123.  * paulaBase (private)
  124.     STRUCTURE paulaBase,LIB_SIZE
  125.     UBYTE    pb_Flags
  126.     UBYTE    pb_Pad1
  127.     UWORD    pb_Pad2
  128.     APTR    pb_SysLib
  129.     ULONG    pb_SegList
  130.     APTR    pb_GfxLib
  131.     APTR    pb_UtilLib
  132.     APTR    pb_DosLib
  133.     APTR    pb_IntuiLib
  134.     APTR    pb_TimerLib
  135.     APTR    pb_MiscResource
  136.     APTR    pb_CardResource
  137.     LABEL    paulaBase_SIZEOF
  138.  
  139.  * channel (private) used in DMA mode
  140.  
  141.     STRUCTURE channel,0
  142.     UWORD    ch_IntMask            ;This channels interrupt bit
  143.     UWORD    ch_DMAMask            ;This channels DMA bit
  144.     UWORD    ch_Stereo            ;0 = Left, 1 = Right
  145.     UWORD    ch_DMALength
  146.     UBYTE    ch_EndOfSample            ;Flag
  147.     UBYTE    ch_NoInt            ;SetFreq() must not cause interrupt
  148.     UWORD    ch_Pad
  149.     APTR    ch_RegBase            ;This channels hardware register base
  150.  
  151.     ULONG    ch_Cleared            ;Samples already cleared
  152.     ULONG    ch_Cleared2            ;Samples already cleared
  153.  
  154.     ULONG    ch_Count            ;How mant samples played? (In samples)
  155.  
  156.     APTR    ch_Address            ;Current sample address
  157.     APTR    ch_NextAddress            ;Next sample address
  158.  
  159.     ULONG    ch_Offset            ;Where are we playing? (In samples)
  160.     ULONG    ch_NextOffset            ;Next...
  161.  
  162.     ULONG    ch_Length            ;Current sample length (In samples)
  163.     ULONG    ch_NextLength            ;Next sample length
  164.  
  165.     ULONG    ch_Type                ;Current sample type
  166.     ULONG    ch_NextType            ;Next sample type
  167.  
  168.     LABEL    ch_PerVol
  169.     UWORD    ch_Period            ;Current period (0 = stopped)
  170.     UWORD    ch_Volume            ;Current volume (scaled)
  171.     LABEL    ch_NextPerVol
  172.     UWORD    ch_NextPeriod            ;Next period
  173.     UWORD    ch_NextVolume            ;Next volume  (scaled)
  174.  
  175. ;    ULONG    ch_AudPerVol
  176.  
  177.     UWORD    ch_VolumeNorm
  178.     UWORD    ch_NextVolumeNorm
  179.  
  180.     UWORD    ch_Scale            ;Current frequency scale (2^ch_Scale)
  181.     UWORD    ch_NextScale            ;Next frequency scale
  182.  
  183.     STRUCT    ch_SndMsg,AHISoundMessage_SIZEOF
  184.  
  185.     LABEL    channel_SIZEOF
  186.  
  187.  * sound (private) used in DMA mode
  188.  
  189.     STRUCTURE sound,0
  190.     ULONG    so_Type
  191.     APTR    so_Address
  192.     ULONG    so_Length
  193.     LABEL    sound_SIZEOF
  194.  
  195.  * paula (private) ahiac_DriverData points to this structure.
  196.     STRUCTURE paula,0
  197.     UBYTE    p_Flags
  198.     UBYTE    p_Parallel            ;TRUE if parport allocated
  199.     UBYTE    p_Filter            ;TRUE if filter was on when alocating
  200.     UBYTE    p_Pad0
  201.     UWORD    p_DisableCount            ;AHIsub_Enable/AHIsub_Disable cnt
  202.     UWORD    p_IRQMask
  203.  
  204.     APTR    p_PaulaBase            ;Pointer to library base (DMA only)
  205.     APTR    p_AudioCtrl            ;Backpointer to AudioCtrl struct.
  206.  
  207.     ULONG    p_AudioFreq            ;PAL/NTSC clock constant
  208.     UWORD    p_SwapChannels            ;TRUE if left/right should be swapped
  209.     UWORD    p_ScreenIsDouble        ;TRUE if screen mode allows >28kHz
  210.     ULONG    p_MinBufferLength        ;Minimum length of chipmem playbuffer
  211.     APTR    p_CalibrationTable        ;Pointer to 14 bit conversion tables
  212.  
  213.     APTR    p_DMAbuffer            ;Chipmem play buffer
  214.     ULONG    p_DoubleBufferOffset        ;Buffer flag
  215.  
  216.     LABEL    p_AudPtrs            ; Pointers to chipmem play buffer
  217.     APTR    p_AudPtr1A
  218.     APTR    p_AudPtr2A
  219.     APTR    p_AudPtr3A
  220.     APTR    p_AudPtr4A
  221.     APTR    p_AudPtr1B
  222.     APTR    p_AudPtr2B
  223.     APTR    p_AudPtr3B
  224.     APTR    p_AudPtr4B
  225.  
  226.     APTR    p_audioport            ;For audio.device
  227.     APTR    p_audioreq            ;For audio.device
  228.     ULONG    p_audiodev            ;For audio.device
  229.     APTR    p_ParBitsUser            ;Parallel port locking
  230.     APTR    p_ParPortUser            ;Parallel port locking
  231.     APTR    p_SerBitsUser            ;Serial port locking
  232.     APTR    p_CardHandle            ;Aura PCMCIA card hanle
  233.  
  234.     STRUCT    p_PlayInt,IS_SIZE        ;Player hardware interrupt
  235.     STRUCT    p_PlaySoftInt,IS_SIZE        ;Player software interrupt (mixing only)
  236.     STRUCT    p_RecInt,IS_SIZE        ;Recorder hardware interrupt (mixing only)
  237.     STRUCT    p_RecSoftInt,IS_SIZE        ;Recorder software interrupt (mixing only)
  238.  
  239.     UWORD    p_AudPer            ;Playback period (mixing only)
  240.     UWORD    p_OutputVolume            ;Hardware volume (mixing only)
  241.     UWORD    p_MonitorVolume            ;Monitor volume (mixing only)
  242.     UWORD    p_Input                ;Input select (mixing only)
  243.  
  244.     ULONG    p_LoopTimes            ;(mixing only)
  245.  
  246.     LABEL    p_PlayerHookRegs        ;PlayerHook
  247.     APTR    p_PlayerHook
  248.     ULONG    p_Reserved
  249.     FPTR    p_PlayerEntry            ;p_PlayerHook->h_Entry
  250.  
  251.     LABEL    p_MixHookRegs            ;MixingHook (mixing only)
  252.     APTR    p_MixHook
  253.     APTR    p_Mixbuffer
  254.     FPTR    p_MixEntry            ;p_MixHook->h_Entry
  255.  
  256.     LABEL    p_RecIntDataAura        ;Record data structure for Aura sampl.
  257.     APTR    p_AuraAddress            ;DO NOT CHANGE ORDER!
  258.     LABEL    p_RecIntData            ;Record data structure
  259.     APTR    p_RecFillPtr
  260.     UWORD    p_RecFillCount
  261.     UWORD    p_Pad2
  262.     APTR    p_RecBuffer1
  263.     APTR    p_RecBuffer2
  264.     APTR    p_RecSoftIntPtr
  265.  
  266.     LABEL    p_RecordMessage            ;Message used with SamplerFunc()
  267.     ULONG    p_rmType
  268.     APTR    p_rmBuffer
  269.     ULONG    p_rmLength
  270.  
  271.     ULONG    p_EClock            ;System E clock freq. (DMA only)
  272.     ULONG    p_EPeriod            ;PlayerFunc() E clk period (DMA only)
  273.     STRUCT    p_EAlarm,EV_SIZE        ;E Clock to wait for (DMA only)
  274.     STRUCT    p_TimerPort,MP_SIZE        ;(DMA only)
  275.     STRUCT    p_TimerInt,IS_SIZE        ;(DMA only)
  276.     APTR    p_TimerReq            ;Used to drive PlayerFunc() (DMA only)
  277.     UBYTE    p_TimerDev            ;(DMA only)
  278.     UBYTE    p_TimerPad
  279.     UWORD    p_TimerCommFlag            ;Used to end timer (DMA only)
  280.  
  281.     ULONG    p_MasterVolume            ;Effect parameter (DMA only)
  282.     APTR    p_ChannelInfo            ;Effect structure (DMA only)
  283.  
  284.     APTR    p_Sounds
  285.     STRUCT    p_Channels,channel_SIZEOF*4    ;DMA playback channel info
  286.  
  287.     STRUCT    p_CalibrationArray,256        ;14 bit calibration prefs
  288.  
  289.     LABEL    paula_SIZEOF
  290.  
  291. * p_Flags
  292.     BITDEF    P,14BIT,0
  293.     BITDEF    P,HIFI,1
  294. PB_STEREO    EQU    AHIACB_STEREO        ;=2
  295. PF_STEREO    EQU    AHIACF_STEREO
  296.     BITDEF    P,DMA,3
  297.  
  298. Start:
  299.     moveq    #-1,d0
  300.     rts
  301.  
  302. RomTag:
  303.     DC.W    RTC_MATCHWORD
  304.     DC.L    RomTag
  305.     DC.L    EndCode
  306.     DC.B    RTF_AUTOINIT
  307.     DC.B    VERSION                ;version
  308.     DC.B    NT_LIBRARY
  309.     DC.B    0                ;pri
  310.     DC.L    LibName
  311.     DC.L    IDString
  312.     DC.L    InitTable
  313.  
  314. LibName:    dc.b    "paula.audio",0
  315. IDString:    VSTRING
  316. gfxName:    GRAPHICSNAME
  317. utilName:    UTILITYNAME
  318. dosName:    DOSNAME
  319. intuiName:    dc.b    "intuition.library",0
  320. timerName:    dc.b    "timer.device",0
  321. miscName:    MISCNAME
  322. cardName:    dc.b    "card.resource",0
  323. filterVar:    dc.b    "AHIpaulaFilterFreq",0
  324. screenVar:    dc.b    "AHIpaulaSampleLimit",0
  325. bufferVar:    dc.b    "AHIpaulaBufferLength",0
  326. swapVar:    dc.b    "AHIpaulaSwapChannels",0
  327.     cnop    0,2
  328.  
  329. InitTable:
  330.     DC.L    paulaBase_SIZEOF
  331.     DC.L    funcTable
  332.     DC.L    dataTable
  333.     DC.L    initRoutine
  334.  
  335. funcTable:
  336.     dc.l    Open
  337.     dc.l    Close
  338.     dc.l    Expunge
  339.     dc.l    Null
  340. *
  341.     dc.l    AHIsub_AllocAudio
  342.     dc.l    AHIsub_FreeAudio
  343.     dc.l    AHIsub_Disable
  344.     dc.l    AHIsub_Enable
  345.     dc.l    AHIsub_Start
  346.     dc.l    AHIsub_Update
  347.     dc.l    AHIsub_Stop
  348.     dc.l    AHIsub_SetVol
  349.     dc.l    AHIsub_SetFreq
  350.     dc.l    AHIsub_SetSound
  351.     dc.l    AHIsub_SetEffect
  352.     dc.l    AHIsub_LoadSound
  353.     dc.l    AHIsub_UnloadSound
  354.     dc.l    AHIsub_GetAttr
  355.     dc.l    AHIsub_HardwareControl
  356.     dc.l    -1
  357.  
  358. dataTable:
  359.     INITBYTE    LN_TYPE,NT_LIBRARY
  360.     INITLONG    LN_NAME,LibName
  361.     INITBYTE    LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  362.     INITWORD    LIB_VERSION,VERSION
  363.     INITWORD    LIB_REVISION,REVISION
  364.     INITLONG    LIB_IDSTRING,IDString
  365.     DC.L        0
  366.  
  367. initRoutine:
  368.     movem.l    d1/a0/a1/a5/a6,-(sp)
  369.     move.l    d0,a5
  370.     move.l    a6,pb_SysLib(a5)
  371.     move.l    a0,pb_SegList(a5)
  372.     lea    gfxName(pc),a1
  373.     moveq    #0,d0
  374.     call    OpenLibrary
  375.     move.l    d0,pb_GfxLib(a5)
  376.     bne.b    .gfxOK
  377.     ALERT    AG_OpenLib|AO_GraphicsLib
  378.     moveq    #0,d0
  379.     bra    .exit
  380. .gfxOK
  381.     lea    utilName(pc),a1
  382.     moveq    #0,d0
  383.     call    OpenLibrary
  384.     move.l    d0,pb_UtilLib(a5)
  385.     bne.b    .utilOK
  386.     ALERT    AG_OpenLib|AO_UtilityLib
  387.     moveq    #0,d0
  388.     bra    .exit
  389. .utilOK
  390.     lea    dosName(pc),a1
  391.     moveq    #0,d0
  392.     call    OpenLibrary
  393.     move.l    d0,pb_DosLib(a5)
  394.     bne.b    .dosOK
  395.     ALERT    AG_OpenLib|AO_DOSLib
  396.     moveq    #0,d0
  397.     bra    .exit
  398. .dosOK
  399.     lea    intuiName(pc),a1
  400.     moveq    #0,d0
  401.     call    OpenLibrary
  402.     move.l    d0,pb_IntuiLib(a5)
  403.     bne.b    .intuiOK
  404.     ALERT    AG_OpenLib|AO_Intuition
  405.     moveq    #0,d0
  406.     bra    .exit
  407. .intuiOK
  408.     lea    miscName(pc),a1
  409.     call    OpenResource
  410.     move.l    d0,pb_MiscResource(a5)
  411.     bne.b    .miscOK
  412.     ALERT    AG_OpenRes|AO_MiscRsrc
  413.     moveq    #0,d0
  414.     bra    .exit
  415. .miscOK
  416.     lea    cardName(pc),a1
  417.     call    OpenResource
  418.     move.l    d0,pb_CardResource(a5)        ;Don't fail on error
  419.  
  420.     move.l    a5,d0
  421. .exit
  422.     movem.l    (sp)+,d1/a0/a1/a5/a6
  423.     rts
  424.  
  425. Open:
  426.     moveq    #0,d0
  427.     addq.w    #1,LIB_OPENCNT(a6)
  428.     bclr.b    #LIBB_DELEXP,pb_Flags(a6)
  429.     move.l    a6,d0
  430. .exit
  431.     rts
  432.  
  433. Close:
  434.     moveq    #0,d0
  435.     subq.w    #1,LIB_OPENCNT(a6)
  436.     bne.b    .exit
  437.     btst.b    #LIBB_DELEXP,pb_Flags(a6)
  438.     beq.b    .exit
  439.     bsr    Expunge
  440. .exit
  441.     rts
  442.  
  443. Expunge:
  444.     movem.l    d1/d2/a0/a1/a5/a6,-(sp)
  445.     move.l    a6,a5
  446.     move.l    pb_SysLib(a5),a6
  447.     tst.w    LIB_OPENCNT(a5)
  448.     beq.b    .notopen
  449.     bset.b    #LIBB_DELEXP,pb_Flags(a5)
  450.     moveq    #0,d0
  451.     bra.b    .Expunge_end
  452. .notopen
  453.     move.l    pb_IntuiLib(a5),a1
  454.     call    CloseLibrary
  455.  
  456.     move.l    pb_DosLib(a5),a1
  457.     call    CloseLibrary
  458.  
  459.     move.l    pb_UtilLib(a5),a1
  460.     call    CloseLibrary
  461.  
  462.     move.l    pb_GfxLib(a5),a1
  463.     call    CloseLibrary
  464.  
  465.     move.l    pb_SegList(a5),d2
  466.     move.l    a5,a1
  467.     call    Remove
  468.  
  469.     moveq    #0,d0
  470.     move.l    a5,a1
  471.     move.w    LIB_NEGSIZE(a5),d0
  472.     sub.l    d0,a1
  473.     add.w    LIB_POSSIZE(a5),d0
  474.     call    FreeMem
  475.     move.l    d2,d0
  476. .Expunge_end
  477.     movem.l    (sp)+,d1/d2/a0/a1/a5/a6
  478.     rts
  479.  
  480. Null:
  481.     moveq    #0,d0
  482.     rts
  483.  
  484. * BeginIO(ioRequest)(a1) (From amiga.lib)
  485. BeginIO:
  486.     move.l    a1,a0        ;probably not neccesary
  487.     push    a6
  488.     move.l    IO_DEVICE(a1),a6
  489.     jsr    -30(a6)
  490.     pop    a6
  491.     rts
  492.  
  493.  
  494. ****** [driver].audio/--background-- ****************************************
  495. *
  496. *   OVERVIEW
  497. *
  498. *       GENERAL PROGRAMMING GUIDLINES
  499. *
  500. *       The driver must be able to be OpenLibrary()'ed even if the
  501. *       hardware is not present. If a library the driver uses fails
  502. *       to open, it is ok to fail at the library init routine, but please
  503. *       avoid it if possible.
  504. *
  505. *       Please note that this document could be much better, but since not
  506. *       many will ever need to read it, it will probably stay this way.
  507. *       Don't hesitate to contact Martin Blom when you're writing a driver!
  508. *
  509. *       DRIVER VERSIONS
  510. *
  511. *       The lowest supported driver version is 2. If you use any feature
  512. *       introduced in later versions of AHI, you should set the driver
  513. *       version to the same version as the features were introduced with.
  514. *       Example: You use PreTimer() and PostTimer(), and since these
  515. *       calls were added in V4 of ahi.device, your driver's version should
  516. *       be 4, too.
  517. *
  518. *       AUDIO ID NUMBERS
  519. *
  520. *       Just some notes about selecting ID numbers for different modes:
  521. *       It is up to the driver programmer to chose which modes should be
  522. *       available to the user. Take care when selecting.
  523. *
  524. *       The upper word is the hardware ID, and can only be allocated by
  525. *       Martin Blom <lcs@lysator.liu.se>. The lower word is free, but in
  526. *       order to allow enhancements, please only use bit 0 to 4 for modes!
  527. *       If your driver supports multiple sound cards, use bit 12-15 to
  528. *       select card (first one is 0). If your sound card has multiple
  529. *       AD/DA converters, you can use bit 8-11 to select them (the first
  530. *       should be 0).
  531. *
  532. *       Set the remaining bits to zero.
  533. *
  534. *       Use AHI:Developer/Support/ScanAudioModes to have a look at the modes
  535. *       currently available. Use AHI:Developer/Support/sift to make sure your
  536. *       mode descriptor file is a legal IFF file.
  537. *
  538. *       I do reserve the right to change the rules if I find them incorrect!
  539. *
  540. *****************************************************************************
  541. *
  542. *
  543.  
  544.  
  545. ****** [driver].audio/AHIsub_AllocAudio *************************************
  546. *
  547. *   NAME
  548. *       AHIsub_AllocAudio -- Allocates and initializes the audio hardware.
  549. *
  550. *   SYNOPSIS
  551. *       result = AHIsub_AllocAudio( tags, audioctrl);
  552. *       D0                          A1    A2
  553. *
  554. *       ULONG AHIsub_AllocAudio( struct TagItem *, struct AHIAudioCtrlDrv * );
  555. *
  556. *   IMPLEMENTATION
  557. *       Allocate and initialize the audio hardware. Decide if and how you
  558. *       wish to use the mixing routines provided by 'ahi.device', by looking
  559. *       in the AHIAudioCtrlDrv structure and parsing the tag list for tags
  560. *       you support.
  561. *
  562. *       1) Use mixing routines with timing:
  563. *           You will need to be able to play any number of samples from
  564. *           about 80 up to 65535 with low overhead.
  565. *           · Update AudioCtrl->ahiac_MixFreq to nearest value that your
  566. *             hardware supports.
  567. *           · Return AHISF_MIXING|AHISF_TIMING.
  568. *
  569. *       2) Use mixing routines without timing:
  570. *           If the hardware can't play samples with any length, use this
  571. *           alternative and provide timing yourself. The buffer must
  572. *           take less than about 20 ms to play, preferable less than 10!
  573. *           · Update AudioCtrl->ahiac_MixFreq to nearest value that your
  574. *             hardware supports.
  575. *           · Store the number of samples to mix each pass in
  576. *             AudioCtrl->ahiac_BuffSamples.
  577. *           · Return AHISF_MIXING
  578. *           Alternatively, you can use the first method and call the
  579. *           mixing hook several times in a row to fill up a buffer.
  580. *           In that case, AHIsub_GetAttr(AHIDB_MaxPlaySamples) should
  581. *           return the size of the buffer plus AudioCtrl->ahiac_MaxBuffSamples.
  582. *           If the buffer is so large that it takes more than (approx.) 10 ms to
  583. *           play it for high sample frequencies, AHIsub_GetAttr(AHIDB_Realtime)
  584. *           should return FALSE.
  585. *
  586. *       3) Don't use mixing routines:
  587. *           If your hardware can handle everything without using the CPU to
  588. *           mix the channels, you tell 'ahi.device' this by not setting
  589. *           either the AHISB_MIXING or the AHISB_TIMING bit.
  590. *
  591. *       If you can handle stereo output from the mixing routines, also set
  592. *       bit AHISB_KNOWSTEREO.
  593. *
  594. *       If you can handle hifi (32 bit) output from the mixing routines,
  595. *       set bit AHISB_KNOWHIFI.
  596. *
  597. *       If this driver can be used to record samples, set bit AHISB_CANRECORD,
  598. *       too (regardless if you use the mixing routines in AHI or not).
  599. *
  600. *       If the sound card has hardware to do DSP effects, you can set the
  601. *       AHISB_CANPOSTPROCESS bit. The output from the mixing routines will 
  602. *       then be two separate buffers, one wet and one dry. You should then
  603. *       apply the Fx on the wet buffer, and post-mix the two buffers before
  604. *       you send the samples to the DAC. (V4)
  605. *
  606. *   INPUTS
  607. *       tags - pointer to a taglist.
  608. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  609. *
  610. *   TAGS
  611. *       The tags are from the audio database (AHIDB_#? in <devices/ahi.h>),
  612. *       NOT the tag list the user called ahi.device/AHI_AllocAudio() with.
  613. *
  614. *   RESULT
  615. *       Flags, defined in <libraries/ahi_sub.h>.
  616. *
  617. *   EXAMPLE
  618. *
  619. *   NOTES
  620. *       You don't have to clean up on failure, AHIsub_FreeAudio() will
  621. *       always be called.
  622. *
  623. *   BUGS
  624. *
  625. *   SEE ALSO
  626. *       AHIsub_FreeAudio(), AHIsub_Start()
  627. *
  628. *****************************************************************************
  629. *
  630. *
  631.  
  632. AHIsub_AllocAudio:
  633.     PRINTF    2,"H"
  634.     PRINTF    2,"AHIsub_AllocAudio()"
  635.  
  636.     pushm    std
  637.     move.l    a6,a5
  638.  
  639.     move.l    a1,d3
  640.  
  641.  
  642. * Allocate the 'paula' structure (our variables)
  643.     move.l    pb_SysLib(a5),a6
  644.     move.l    #paula_SIZEOF,d0
  645.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  646.     call    AllocVec
  647.     move.l    d0,ahiac_DriverData(a2)
  648.     beq    .error_nopaula
  649.     move.l    d0,a3
  650.  
  651. * Initialize some fields...
  652.     move.b    #-1,p_TimerDev(a3)
  653.     move.l    #-1,p_audiodev(a3)
  654.     move.l    #-1,p_ParBitsUser(a3)
  655.     move.l    #-1,p_ParPortUser(a3)
  656.     move.l    #-1,p_SerBitsUser(a3)
  657.     move.l    a5,p_PaulaBase(a3)
  658.     move.l    a2,p_AudioCtrl(a3)
  659.     lea    p_RecSoftInt(a3),a0
  660.     move.l    a0,p_RecSoftIntPtr(a3)
  661.     move.l    #AHIST_S16S,p_rmType(a3)
  662.     move.l    #RECORDSAMPLES,p_rmLength(a3)
  663.     move.w    #64,p_OutputVolume(a3)
  664.     move.l    #$10000,p_MasterVolume(a3)
  665.  
  666. * Translate tags to flags
  667.     move.l    pb_UtilLib(a5),a6
  668.  
  669.     move.l    ahiac_Flags(a2),d2
  670.     and.b    #PF_STEREO,d2            ;same as AHIACF_STEREO
  671.  
  672.     move.l    #AHIDB_Paula14Bit,d0
  673.     moveq    #FALSE,d1
  674.     move.l    d3,a0                ;tag list
  675.     call    GetTagData
  676.     tst.l    d0
  677.     beq.b    .no14bit
  678.     or.b    #PF_14BIT,d2
  679. .no14bit
  680.     move.l    #AHIDB_HiFi,d0
  681.     moveq    #FALSE,d1
  682.     move.l    d3,a0                ;tag list
  683.     call    GetTagData
  684.     tst.l    d0
  685.     beq.b    .noHiFi
  686.     or.b    #PF_HIFI,d2
  687. .noHiFi
  688.     move.l    #AHIDB_PaulaDMA,d0
  689.     moveq    #FALSE,d1
  690.     move.l    d3,a0                ;tag list
  691.     call    GetTagData
  692.     tst.l    d0
  693.     beq.b    .noDMA
  694.     or.b    #PF_DMA,d2
  695. .noDMA
  696.  
  697.     move.b    p_Flags(a3),d1
  698.     and.b    #~(PF_STEREO|PF_14BIT|PF_HIFI|PF_DMA),d1
  699.     or.b    d2,d1
  700.     move.b    d1,p_Flags(a3)
  701.  
  702.     move.l    #PALFREQ,d2            ;PAL
  703.     move.l    pb_GfxLib(a5),a0
  704.     move.w    gb_DisplayFlags(a0),d0
  705.     btst    #REALLY_PALn,d0
  706.     bne.b    .1
  707.     move.l    #NTSCFREQ,d2            ;NTSC
  708. .1
  709.     move.l    d2,p_AudioFreq(a3)
  710.     bsr    checkvideo
  711.     move.w    d0,p_ScreenIsDouble(a3)
  712.  
  713. * Check if a table should be used (14 bit calibration)
  714.     move.l    #AHIDB_PaulaTable,d0
  715.     moveq    #0,d1
  716.     move.l    d3,a0                ;tag list
  717.     call    GetTagData
  718.     tst.l    d0
  719.     beq    .notable
  720.  
  721. * Load 'ENV:CyberSound/SoundDrivers/14Bit_Calibration', allocate
  722. * and initialize the table.
  723. * FIXIT: The calibration file should move to a special chunk in
  724. * 'DEVS:AudioModes/PAULA'.
  725.     move.l    pb_DosLib(a5),a6
  726.     lea    .calibname(pc),a0
  727.     move.l    a0,d1
  728.     move.l    #MODE_OLDFILE,d2
  729.     call    Open
  730.     move.l    d0,d4
  731.     beq    .nocalib
  732.     move.l    d0,d1
  733.     lea    p_CalibrationArray(a3),a0
  734.     move.l    a0,d2
  735.     move.l    #256,d3
  736.     call    Read
  737.     cmp.l    d0,d3
  738.     beq    .tableloaded
  739. .nocalib
  740. ; Fill defaults
  741.     lea    p_CalibrationArray(a3),a0
  742.     move.w    #254-1,d0
  743. .initcalib
  744.     move.b    #$55,(a0)+
  745.     dbf    d0,.initcalib
  746.     move.b    #$7f,(a0)+
  747. .tableloaded
  748.     move.l    d4,d1
  749.     beq.b    .nofile
  750.     call    Close
  751. .nofile
  752.     move.l    pb_SysLib(a5),a6
  753.     move.l    #65536*2,d0
  754.     move.l    #MEMF_PUBLIC,d1
  755.     call    AllocVec
  756.     move.l    d0,p_CalibrationTable(a3)
  757.     beq.b    .notable
  758.     move.l    d0,a0            ;table
  759.     lea    p_CalibrationArray(a3),a1
  760.     bsr.w    _CreateTable
  761. .notable
  762.  
  763. * Get the minimum chip buffer size
  764.     moveq    #0,d5                ;Default
  765.     move.l    pb_DosLib(a5),a6
  766.     subq.l    #8,sp                ;local label
  767.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  768.     lea    bufferVar(pc),a0
  769.     move.l    a0,d1
  770.     move.l    sp,d2
  771.     moveq.l    #8,d3
  772.     moveq.l    #0,d4
  773.     call    GetVar
  774.     cmp.l    #-1,d0
  775.     beq    .gotlength
  776.     move.l    sp,d1
  777.     pea.l    0.w
  778.     move.l    sp,d2
  779.     call    StrToLong
  780.     move.l    (sp)+,d5
  781. .gotlength
  782.     addq.l    #8,sp
  783. ; d5 is now the buffer length
  784.     move.l    d5,p_MinBufferLength(a3)
  785.  
  786. * Check if we should swap left & right channels
  787.     moveq    #0,d5                ;Default
  788.     move.l    pb_DosLib(a5),a6
  789.     subq.l    #8,sp                ;local label
  790.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  791.     lea    swapVar(pc),a0
  792.     move.l    a0,d1
  793.     move.l    sp,d2
  794.     moveq.l    #8,d3
  795.     moveq.l    #0,d4
  796.     call    GetVar
  797.     cmp.l    #-1,d0
  798.     beq    .gotswap
  799.     move.l    sp,d1
  800.     pea.l    0.w
  801.     move.l    sp,d2
  802.     call    StrToLong
  803.     move.l    (sp)+,d5
  804. .gotswap
  805.     addq.l    #8,sp
  806. ; d5 is now the buffer length
  807.     move.w    d5,p_SwapChannels(a3)
  808.  
  809. * allocate audio.device
  810.     move.l    pb_SysLib(a5),a6
  811.     call    CreateMsgPort
  812.     move.l    d0,p_audioport(a3)
  813.     beq    .error_noport
  814.     moveq    #ioa_SIZEOF,d0
  815.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  816.     call    AllocVec
  817.     move.l    d0,p_audioreq(a3)
  818.     beq    .error_noreqmem
  819.     move.l    d0,a0
  820.     move.l    p_audioport(a3),MN_REPLYPORT(a0)
  821.     clr.w    ioa_AllocKey(a0)
  822.     move.b    #127,LN_PRI(a0)            ;steal it!
  823.     lea    .audiochannelarray(pc),a1
  824.     move.l    a1,ioa_Data(a0)
  825.     move.l    #1,ioa_Length(a0)
  826.     lea    .audioname(pc),a0
  827.     moveq    #0,d0
  828.     move.l    p_audioreq(a3),a1
  829.     moveq    #0,d1
  830.     call    OpenDevice
  831.     move.l    d0,p_audiodev(a3)
  832.     bne    .error_noaudiodev        ;somebody already owns the hardware (could be us!)
  833.     move.l    p_audioreq(a3),a1
  834.     move.w    #CMD_RESET,IO_COMMAND(a1)
  835.     bsr.w    BeginIO                ;clear attach, stop sound.
  836.     move.l    p_audioport(a3),a0
  837.     call    WaitPort
  838.     move.l    p_audioport(a3),a0
  839.     call    GetMsg
  840.  
  841.     move.l    pb_DosLib(a5),a6
  842.     moveq    #1,d1
  843.     call    Delay
  844.  
  845. * Set dummy interrupt handler
  846.     move.l    pb_SysLib(a5),a6
  847.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  848.  
  849.     lea    p_PlayInt(a3),a1
  850.     moveq    #INTB_AUD0,d0
  851.     call    SetIntVector
  852.     lea    p_PlayInt(a3),a1
  853.     moveq    #INTB_AUD1,d0
  854.     call    SetIntVector
  855.     lea    p_PlayInt(a3),a1
  856.     moveq    #INTB_AUD2,d0
  857.     call    SetIntVector
  858.     lea    p_PlayInt(a3),a1
  859.     moveq    #INTB_AUD3,d0
  860.     call    SetIntVector
  861.  
  862. * test if mode supports recording
  863.     move.b    p_Flags(a3),d0
  864.     and.b    #PF_14BIT|PF_DMA,d0
  865.     bne    .dontgetsampler            ;no record if 14 bit and DMA modes
  866.  
  867. * try to allocate parallel port
  868.     clr.b    p_Parallel(a3)
  869.     move.l    pb_MiscResource(a5),a6
  870.     moveq    #MR_PARALLELBITS,d0
  871.     lea    IDString(pc),a1
  872.     jsr    MR_ALLOCMISCRESOURCE(a6)
  873.     move.l    d0,p_ParBitsUser(a3)
  874.     bne    .no_parrallel
  875.     moveq    #MR_PARALLELPORT,d0
  876.     lea    IDString(pc),a1
  877.     jsr    MR_ALLOCMISCRESOURCE(a6)
  878.     move.l    d0,p_ParPortUser(a3)
  879.     bne    .no_parrallel
  880.  
  881.     move.b    #TRUE,p_Parallel(a3)
  882.     move.b    #0,_ciaa+ciaddrb            ;make PB0-PB7 inputs
  883. .no_parrallel
  884.  
  885. * allocate Aura sampler
  886.     clr.l    p_AuraAddress(a3)
  887.     move.l    pb_CardResource(a5),d0
  888.     beq    .no_aura
  889.     move.l    d0,a6
  890.     call    GetCardMap
  891.     tst.l    d0
  892.     beq    .no_aura
  893.     move.l    d0,a0
  894.     move.l    cmm_IOMemory(a0),d2
  895.     beq    .no_aura
  896.  
  897.     move.l    pb_SysLib(a5),a6
  898.     moveq    #CardHandle_SIZEOF,d0
  899.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  900.     call    AllocVec
  901.     move.l    d0,p_CardHandle(a3)
  902.     beq    .no_aura
  903.  
  904.     move.l    pb_CardResource(a5),a6
  905.     move.l    d0,a1
  906.     move.l    #IDString,LN_NAME(a1)
  907.     move.b    #CARDF_RESETREMOVE|CARDF_IFAVAILABLE,cah_CardFlags(a1)
  908.     call    OwnCard
  909.     tst.l    d0
  910.     bne    .no_aura
  911.  
  912.     move.l    p_CardHandle(a3),a1
  913.     call    BeginCardAccess
  914.  
  915.     move.l    d2,p_AuraAddress(a3)
  916. .no_aura
  917. .dontgetsampler
  918.  
  919.  
  920.  
  921. * initialize interrupts (Only dummy function pointers at this time)
  922.  
  923.  * p_PlayInt (the main playback interrupt)
  924.     move.b    #NT_INTERRUPT,LN_TYPE+p_PlayInt(a3)
  925.     move.l    #LibName,LN_NAME+p_PlayInt(a3)
  926.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  927.     move.l    a3,IS_DATA+p_PlayInt(a3)
  928.  
  929.  * p_PlaySoftInt (caused by p_PlayInt, here are the mixing and conversion done)
  930.     move.b    #NT_INTERRUPT,LN_TYPE+p_PlaySoftInt(a3)
  931.     move.l    #LibName,LN_NAME+p_PlaySoftInt(a3)
  932.     move.l    #SoftInt_Dummy,IS_CODE+p_PlaySoftInt(a3)
  933.     move.l    a3,IS_DATA+p_PlaySoftInt(a3)
  934.  
  935.  * p_RecInt (the interrupt used for recording)
  936.     move.b    #NT_INTERRUPT,LN_TYPE+p_RecInt(a3)
  937.     move.l    #LibName,LN_NAME+p_RecInt(a3)
  938.     move.l    #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
  939.     clr.l    IS_DATA+p_RecInt(a3)
  940.  
  941.  * p_RecSoftInt (caused by p_RecInt when the record buffer has been filled)
  942.     move.b    #32,LN_PRI+p_RecSoftInt(a3)
  943.     move.b    #NT_INTERRUPT,LN_TYPE+p_RecSoftInt(a3)
  944.     move.l    #LibName,LN_NAME+p_RecSoftInt(a3)
  945.     move.l    #RecordSoftInt,IS_CODE+p_RecSoftInt(a3)
  946.     move.l    a3,IS_DATA+p_RecSoftInt(a3)
  947.  
  948. * Make sure no interrupts occur until AHIsub_Start() is called
  949.     move.w    #INTF_AUDIO,custom+INTENA
  950.     move.w    #INTF_SETCLR,p_IRQMask(a3)
  951.  
  952. * Update ahiac_MixFreq to what the mixing/sampling frequency really is
  953.     move.l    ahiac_MixFreq(a2),d1
  954.     bsr    calcperiod
  955.     move.l    d0,ahiac_MixFreq(a2)        ;store actual freq
  956.  
  957. * Save the filter state
  958.     btst    #1,$bfe001
  959.     seq    p_Filter(a3)
  960.  
  961. * Check the AHIpaulaFilterFreq variable.
  962. * If the mixing frequency is higher than this one, set disable the filter,
  963. * else enable it.
  964.     moveq    #0,d5                ;Default freq
  965.     move.l    pb_DosLib(a5),a6
  966.     subq.l    #8,sp                ;local label
  967.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  968.     lea    filterVar(pc),a0
  969.     move.l    a0,d1
  970.     move.l    sp,d2
  971.     moveq.l    #8,d3
  972.     moveq.l    #0,d4
  973.     call    GetVar
  974.     cmp.l    #-1,d0
  975.     beq    .gotfreq
  976.     move.l    sp,d1
  977.     pea.l    0.w
  978.     move.l    sp,d2
  979.     call    StrToLong
  980.     move.l    (sp)+,d5
  981. .gotfreq
  982.     addq.l    #8,sp
  983. ; d5 is now the freq
  984.  
  985.     cmp.l    ahiac_MixFreq(a2),d5
  986.     bls    .no_filter
  987.     bclr    #1,$bfe001            ;turn audio filter on
  988.     bra    .filter_set
  989. .no_filter
  990.     bset    #1,$bfe001            ;turn audio filter off
  991. .filter_set
  992.  
  993.     btst.b    #PB_DMA,p_Flags(a3)
  994.     beq    .mixing
  995.  
  996.     cmp.w    #4,ahiac_Channels(a2)
  997.     bhi    .error_channels
  998.  
  999.     move.l    p_AudioFreq(a3),ahiac_MixFreq(a2)    ;store actual freq
  1000.  
  1001.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*0+ch_Type(a3)
  1002.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*1+ch_Type(a3)
  1003.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*2+ch_Type(a3)
  1004.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*3+ch_Type(a3)
  1005.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*0+ch_NextType(a3)
  1006.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*1+ch_NextType(a3)
  1007.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*2+ch_NextType(a3)
  1008.     move.l    #AHIST_NOTYPE,p_Channels+channel_SIZEOF*3+ch_NextType(a3)
  1009.     move.w    #0,p_Channels+channel_SIZEOF*0+ch_SndMsg+ahism_Channel(a3)
  1010.     move.w    #1,p_Channels+channel_SIZEOF*1+ch_SndMsg+ahism_Channel(a3)
  1011.     move.w    #2,p_Channels+channel_SIZEOF*2+ch_SndMsg+ahism_Channel(a3)
  1012.     move.w    #3,p_Channels+channel_SIZEOF*3+ch_SndMsg+ahism_Channel(a3)
  1013.  
  1014.     move.l    pb_SysLib(a5),a6
  1015.     move.w    ahiac_Sounds(a2),d0
  1016.     mulu.w    #sound_SIZEOF,d0
  1017.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  1018.     call    AllocVec
  1019.     move.l    d0,p_Sounds(a3)
  1020.     beq    .error_nosoundmem
  1021.  
  1022.     move.l    d0,a0
  1023.     move.w    ahiac_Sounds(a2),d0
  1024.     subq.w    #1,d0
  1025. .fillsounds
  1026.     move.l    #AHIST_NOTYPE,so_Type(a0)
  1027.     add.w    #sound_SIZEOF,a0
  1028.     dbf    d0,.fillsounds
  1029.  
  1030.     tst.w    p_SwapChannels(a3)
  1031.     bne    .swapchannels
  1032.     move.l    #custom+AUD1,p_Channels+channel_SIZEOF*0+ch_RegBase(a3)
  1033.     move.l    #custom+AUD0,p_Channels+channel_SIZEOF*1+ch_RegBase(a3)
  1034.     move.l    #custom+AUD2,p_Channels+channel_SIZEOF*2+ch_RegBase(a3)
  1035.     move.l    #custom+AUD3,p_Channels+channel_SIZEOF*3+ch_RegBase(a3)
  1036.     move.w    #DMAF_AUD1,p_Channels+channel_SIZEOF*0+ch_DMAMask(a3)
  1037.     move.w    #DMAF_AUD0,p_Channels+channel_SIZEOF*1+ch_DMAMask(a3)
  1038.     move.w    #DMAF_AUD2,p_Channels+channel_SIZEOF*2+ch_DMAMask(a3)
  1039.     move.w    #DMAF_AUD3,p_Channels+channel_SIZEOF*3+ch_DMAMask(a3)
  1040.     move.w    #INTF_AUD1,p_Channels+channel_SIZEOF*0+ch_IntMask(a3)
  1041.     move.w    #INTF_AUD0,p_Channels+channel_SIZEOF*1+ch_IntMask(a3)
  1042.     move.w    #INTF_AUD2,p_Channels+channel_SIZEOF*2+ch_IntMask(a3)
  1043.     move.w    #INTF_AUD3,p_Channels+channel_SIZEOF*3+ch_IntMask(a3)
  1044.     move.w    #0,p_Channels+channel_SIZEOF*0+ch_Stereo(a3)
  1045.     move.w    #1,p_Channels+channel_SIZEOF*1+ch_Stereo(a3)
  1046.     move.w    #1,p_Channels+channel_SIZEOF*2+ch_Stereo(a3)
  1047.     move.w    #0,p_Channels+channel_SIZEOF*3+ch_Stereo(a3)
  1048.     bra    .storedbase
  1049. .swapchannels
  1050.     move.l    #custom+AUD0,p_Channels+channel_SIZEOF*0+ch_RegBase(a3)
  1051.     move.l    #custom+AUD1,p_Channels+channel_SIZEOF*1+ch_RegBase(a3)
  1052.     move.l    #custom+AUD3,p_Channels+channel_SIZEOF*2+ch_RegBase(a3)
  1053.     move.l    #custom+AUD2,p_Channels+channel_SIZEOF*3+ch_RegBase(a3)
  1054.     move.w    #DMAF_AUD0,p_Channels+channel_SIZEOF*0+ch_DMAMask(a3)
  1055.     move.w    #DMAF_AUD1,p_Channels+channel_SIZEOF*1+ch_DMAMask(a3)
  1056.     move.w    #DMAF_AUD3,p_Channels+channel_SIZEOF*2+ch_DMAMask(a3)
  1057.     move.w    #DMAF_AUD2,p_Channels+channel_SIZEOF*3+ch_DMAMask(a3)
  1058.     move.w    #INTF_AUD0,p_Channels+channel_SIZEOF*0+ch_IntMask(a3)
  1059.     move.w    #INTF_AUD1,p_Channels+channel_SIZEOF*1+ch_IntMask(a3)
  1060.     move.w    #INTF_AUD3,p_Channels+channel_SIZEOF*2+ch_IntMask(a3)
  1061.     move.w    #INTF_AUD2,p_Channels+channel_SIZEOF*3+ch_IntMask(a3)
  1062.     move.w    #1,p_Channels+channel_SIZEOF*0+ch_Stereo(a3)
  1063.     move.w    #0,p_Channels+channel_SIZEOF*1+ch_Stereo(a3)
  1064.     move.w    #0,p_Channels+channel_SIZEOF*2+ch_Stereo(a3)
  1065.     move.w    #1,p_Channels+channel_SIZEOF*3+ch_Stereo(a3)
  1066. .storedbase
  1067.  
  1068.  
  1069.     moveq    #0,d0
  1070.     bra    .exit
  1071.  
  1072. .mixing
  1073.     moveq    #AHISF_KNOWSTEREO|AHISF_KNOWHIFI|AHISF_CANRECORD|AHISF_MIXING|AHISF_TIMING,d0
  1074.  
  1075. .exit
  1076.     popm    std
  1077.     rts
  1078.  
  1079. .error_noaudiodev
  1080. .error_noreqmem
  1081. .error_noport
  1082. .error_nopaula
  1083. .error_channels
  1084. .error_nosoundmem
  1085.     moveq    #AHISF_ERROR,d0
  1086.     bra.b    .exit
  1087.  
  1088. .audiochannelarray
  1089.     dc.b    1+2+4+8
  1090. .audioname
  1091.     AUDIONAME
  1092. .calibname
  1093.     dc.b    "ENV:CyberSound/SoundDrivers/14Bit_Calibration",0
  1094.     even
  1095. .cardhandle:
  1096.     dc.l    0,0        ;ln_Succ, ln_Pred
  1097.     dc.b    0        ;ln_Type
  1098.     dc.b    0        ;ln_Pri
  1099.     dc.l    IDString    ;ln_Name
  1100.     dc.l    0,0,0        ;cah_CardRemoved, cah_CardInserted, cah_CardStatus
  1101.     dc.b    (CARDF_RESETREMOVE|CARDF_IFAVAILABLE)
  1102.     even
  1103.  
  1104. ;in:
  1105. * d1    MixFreq
  1106. * a3    paula
  1107. * a5    paulaBase
  1108. ;out:
  1109. * d0    New MixFreq
  1110. * d1.w    Period
  1111. ;description:
  1112. *    Calculate and return the best period and the actual frequency.
  1113. calcperiod:
  1114.     PRINTF    2,"calcperiod()"
  1115.     pushm    std
  1116.     move.l    p_AudioFreq(a3),d2
  1117.     move.l    d2,d0
  1118.     move.l    d1,d3
  1119.     move.l    pb_UtilLib(a5),a1
  1120.     jsr    _LVOUDivMod32(a1)
  1121.     lsl.l    #1,d1
  1122.     cmp.l    d3,d1
  1123.     bmi.b    .3
  1124.     addq.l    #1,d0
  1125. .3
  1126.     move.w    d0,d4
  1127. * d4 is now period. Check if is it a valid one, depending on current display mode
  1128.     bsr    checkvideo
  1129.     moveq    #MINPER,d1
  1130.     tst.l    d0
  1131.     bne    .5
  1132.     moveq    #MINPER*2,d1
  1133. .5
  1134.     cmp.w    d1,d4
  1135.     bhs.b    .6
  1136.     move.w    d1,d4
  1137. .6
  1138.     moveq    #0,d1
  1139.     move.w    d4,d1
  1140.     move.l    d2,d0
  1141.     move.l    d1,d3
  1142.     move.l    pb_UtilLib(a5),a1
  1143.     jsr    _LVOUDivMod32(a1)
  1144.     lsl.l    #1,d1
  1145.     cmp.l    d3,d1
  1146.     bmi.b    .4
  1147.     addq.l    #1,d0
  1148. .4
  1149.     move.w    d4,d1
  1150.     popm    std
  1151.     rts
  1152.  
  1153. ;in:
  1154. * a5    paulaBase
  1155. ;out:
  1156. * d0    TRUE if current mode is double
  1157. ;description:
  1158. *    Checks if the current screen mode is doublescan.
  1159. *    This routine is a bit ugly, but it does get the job
  1160. *    done, even if a graphic card is used.
  1161. checkvideo:
  1162.     PRINTF    2,"checkvideo"
  1163.  
  1164.     pushm    std
  1165.  
  1166. * Check the AHIpaulaSampleLimit variable.
  1167. * If 1, allow > 28 kHz frequencies, if 0, don't. If not present,
  1168. * check the screen mode.
  1169.     move.l    pb_DosLib(a5),a6
  1170.     clr.w    -(sp)                ;Initialize local data
  1171.     lea    screenVar(pc),a0
  1172.     move.l    a0,d1
  1173.     move.l    sp,d2
  1174.     moveq.l    #2,d3
  1175.     moveq.l    #0,d4
  1176.     call    GetVar
  1177.     move.w    (sp)+,d1
  1178.     cmp.l    #-1,d0
  1179.     beq    .testfreq
  1180.     cmp.w    #"0"<<8|0,d1
  1181.     beq    .no31k
  1182.     cmp.w    #"1"<<8|0,d1
  1183.     beq    .is31k
  1184.  
  1185. .testfreq
  1186.  
  1187. ; Chip revision test
  1188.  
  1189.     move.l    pb_GfxLib(a5),a0
  1190.     move.b    gb_ChipRevBits0(a0),d0
  1191.     and.b    #GFXF_HR_DENISE|GFXF_AA_LISA,d0
  1192.     beq    .no31k                ; OCS: No 31 kHz modes
  1193.  
  1194. ; Native screen test
  1195.  
  1196.     moveq    #0,d0
  1197.     move.l    pb_IntuiLib(a5),a6
  1198.     call    LockIBase
  1199.     move.l    d0,d2
  1200.     move.l    ib_FirstScreen(a6),a0
  1201.     lea    sc_ViewPort(a0),a0
  1202.     move.l    pb_GfxLib(a5),a6
  1203.     call    GetVPModeID
  1204.     move.l    d2,a0
  1205.     move.l    d0,d2
  1206.     move.l    pb_IntuiLib(a5),a6
  1207.     call    UnlockIBase
  1208.  
  1209.     ; "Check" if native screen
  1210.     move.l    d2,d0
  1211.     and.l    #$40000000,d0
  1212.     bne    .gfxcard
  1213.  
  1214.     ; It is!
  1215.     sub.w    #mtr_SIZEOF,sp            ;local storage
  1216.     suba.l    a0,a0
  1217.     move.l    sp,a1
  1218.     move.l    #mtr_SIZEOF,d0
  1219.     move.l    #DTAG_MNTR,d1
  1220.     move.l    pb_GfxLib(a5),a6
  1221.     call    GetDisplayInfoData
  1222.  
  1223.     moveq    #1,d1
  1224.     add.w    mtr_TotalRows(sp),d1
  1225.     sub.w    mtr_MinRow(sp),d1
  1226.     move.w    mtr_TotalColorClocks(sp),d2
  1227.     mulu.w    mtr_TotalRows(sp),d2
  1228.  
  1229.     add.w    #mtr_SIZEOF,sp            ;restore stack
  1230.     tst.l    d0
  1231.     beq    .no31k
  1232.     ; Calculate TotalColorClocks*TotalRows/(2*(TotalRows-MinRow+1)
  1233.     add.l    d1,d1
  1234.     beq    .no31k
  1235.     divu    d1,d2
  1236.     cmp.w    #64,d2                ; 64 is an round nice number, no?
  1237.     bls    .is31k
  1238.     bra    .no31k
  1239.  
  1240. .gfxcard
  1241.  
  1242. ; Picasso '96 test
  1243.  
  1244.     move.l    pb_SysLib(a5),a6
  1245.     lea    .picasso96(pc),a1
  1246.     call    Forbid                ; Not required, it's just to...
  1247.     call    FindTask
  1248.     call    Permit                ; ...make PatchWork happy.
  1249.     tst.l    d0
  1250.     beq    .cgfx                ; Not P96, assume CyberGraphX
  1251.  
  1252.     move.l    pb_DosLib(a5),a6
  1253.     clr.l    -(sp)                ;Initialize local data
  1254.     lea    .p96amigavideo(pc),a0
  1255.     move.l    a0,d1
  1256.     move.l    sp,d2
  1257.     moveq.l    #4,d3
  1258.     moveq.l    #0,d4
  1259.     call    GetVar
  1260.     move.l    (sp)+,d1
  1261.     swap.w    d1
  1262.     cmp.w    #"31",d1
  1263.     beq    .is31k
  1264.     bra    .no31k
  1265.  
  1266. .cgfx
  1267.  
  1268. ; CybergraphX test
  1269.  
  1270.     move.l    pb_GfxLib(a5),a0
  1271.     cmp.w    #39,LIB_VERSION(a0)
  1272.     beq    .known
  1273.     cmp.w    #40,LIB_VERSION(a0)
  1274.     beq    .known
  1275.     bra    .no31k
  1276. .known
  1277.     move.l    gb_copinit(a0),a0
  1278.     cmp.w    #$01FC,copinit_fm0(a0)        ;Security check (test if really FMODE)
  1279.     bne    .is31k                ;Probably an ECS machine.
  1280.                         ;Assume the user is clever enough
  1281.                         ;to use "AddAudioModes DBLSCAN"....
  1282.     move.w    copinit_fm0+2(a0),d0
  1283.     and.w    #$c000,d0            ;Mask sprite and bitplane double bit
  1284.     beq    .no31k
  1285. .is31k
  1286.     moveq    #TRUE,d0
  1287.     bra    .exit
  1288. .no31k
  1289.     moveq    #FALSE,d0
  1290. .exit
  1291.     popm    std
  1292.     rts
  1293. .picasso96
  1294.     dc.b    "Picasso96",0
  1295. .p96amigavideo
  1296.     dc.b    "Picasso96/AmigaVideo",0
  1297.     even
  1298.  
  1299. ;in:
  1300. * d0    Frequency
  1301. ;out:
  1302. * d0    Closest frequency
  1303. * d1    Index
  1304. findfreq:
  1305.     lea    freqlist(pc),a0
  1306.     cmp.l    (a0),d0
  1307.     bls.b    .2
  1308. .findfreq
  1309.     cmp.l    (a0)+,d0
  1310.     bhi.b    .findfreq
  1311.     move.l    -4(a0),d1
  1312.     sub.l    d0,d1
  1313.     sub.l    -8(a0),d0
  1314.     cmp.l    d1,d0
  1315.     bhs.b    .1
  1316.     subq.l    #4,a0
  1317. .1
  1318.     subq.l    #4,a0
  1319. .2
  1320.     move.l    (a0),d0
  1321.     move.l    a0,d1
  1322.     sub.l    #freqlist,d1
  1323.     lsr.l    #2,d1
  1324.     rts
  1325.  
  1326. freqlist:
  1327.     dc.l    4410                    ; CD/10
  1328.     dc.l    4800                    ; DAT/10
  1329.     dc.l    5513                    ; CD/8
  1330.     dc.l    6000                    ; DAT/8
  1331.     dc.l    7350                    ; CD/6
  1332.     dc.l    8000                    ; µ- and A-Law, DAT/6
  1333.     dc.l    9600                    ; DAT/5
  1334.     dc.l    11025                    ; CD/4
  1335.     dc.l    12000                    ; DAT/4
  1336.     dc.l    14700                    ; CD/3
  1337.     dc.l    16000                    ; DAT/3
  1338.     dc.l    17640                    ; CD/2.5
  1339.     dc.l    18900
  1340.     dc.l    19200                    ; DAT/2.5
  1341.     dc.l    22050                    ; CD/2
  1342.     dc.l    24000                    ; DAT/2
  1343.     dc.l    27429
  1344. FREQUENCIES_OCS        EQU    (*-freqlist)>>2
  1345.     dc.l    29400                    ; CD/1.5
  1346.     dc.l    32000                    ; DAT/1.5
  1347.     dc.l    33075
  1348.     dc.l    37800
  1349.     dc.l    44100                    ; CD
  1350.     dc.l    48000                    ; DAT
  1351. FREQUENCIES        EQU    (*-freqlist)>>2
  1352.     dc.l    -1
  1353.  
  1354. * _CreateTable directly stolen from Christian Buchner's CyberSound
  1355. * audio sub system (with permission).
  1356.  
  1357. * _CreateTable **************************************************************
  1358.  
  1359.         ; Parameters
  1360.  
  1361.         ; a0 = Table address
  1362.         ; (MUST have enough space for 65536 UWORDS)
  1363.         ; a1 = Additive Array
  1364.         ; 256 UBYTEs
  1365.         ;
  1366.         ; the table is organized as follows:
  1367.         ; 32768 UWORDS positive range, ascending order
  1368.         ; 32768 UWORDS negative range, ascending order
  1369.         ; access: (a0,d0.l*2)
  1370.         ; where d0.w is signed word sample data
  1371.         ; and the upper word of d0.l is *cleared!*
  1372.  
  1373.  
  1374. _CreateTable    movem.l    a2/d2-d6,-(sp)
  1375.  
  1376.         lea    128(a1),a2
  1377.  
  1378.         move.l    a2,a1            ; count the number of steps
  1379.         moveq    #128-1,d0        ; in the positive range
  1380.         moveq    #0,d5
  1381. .countpositive    move.b    (a1)+,d1
  1382.         ext.w    d1
  1383.         ext.l    d1
  1384.         add.l    d1,d5
  1385.         dbra    d0,.countpositive    ; d5=number of steps
  1386.         move.l    #32768,d6        ; reset stretch counter
  1387.  
  1388.         move.l    a2,a1            ; middle value in calibdata
  1389.         move.w    #32768-1,d0        ; number of positive values -1
  1390.         moveq    #0,d1            ; HI value
  1391.         moveq    #0,d2            ; LO value
  1392.         moveq    #0,d3            ; counter
  1393. .fetchnext2    move.b    (a1)+,d4        ; add calibtable to counter
  1394.         ext.w    d4
  1395.         add.w    d4,d3
  1396. .outerloop2    tst.w    d3
  1397.         bgt.s    .positive2
  1398. .negative2    addq.w    #1,d1            ; increment HI value
  1399.         sub.w    d4,d2            ; reset LO value
  1400.         bra.s    .fetchnext2
  1401. .positive2    move.b    d1,(a0)+        ; store HI and LO value
  1402.         move.b    d2,(a0)+
  1403.         sub.l    d5,d6            ; stretch the table
  1404.         bpl.s    .repeat2        ; to 32768 entries
  1405.         add.l    #32768,d6
  1406.         addq.w    #1,d2            ; increment LO value
  1407.         subq.w    #1,d3            ; decrement counter
  1408. .repeat2    dbra    d0,.outerloop2
  1409.  
  1410.         move.l    a2,a1            ; count the number of steps
  1411.         moveq    #128-1,d0        ; in the negative range
  1412.         moveq    #0,d5
  1413. .countnegative    move.b    -(a1),d1
  1414.         ext.w    d1
  1415.         ext.l    d1
  1416.         add.l    d1,d5
  1417.         dbra    d0,.countnegative    ; d5=number of steps
  1418.         move.l    #32768,d6        ; reset stretch counter
  1419.  
  1420.         add.l    #2*32768,a0        ; place at the end of the table
  1421.         move.l    a2,a1            ; middle value in calibdata
  1422.         move.w    #32768-1,d0        ; number of negative values -1
  1423.         moveq    #-1,d1            ; HI value
  1424.         moveq    #-1,d2            ; LO value
  1425.         moveq    #0,d3            ; counter
  1426. .fetchnext1    move.b    -(a1),d4        ; add calibtable to counter
  1427.         ext.w    d4
  1428.         add.w    d4,d3
  1429.         add.w    d4,d2            ; maximize LO value
  1430. .outerloop1    tst.w    d3
  1431.         bgt.s    .positive1
  1432. .negative1    subq.w    #1,d1
  1433.         bra.s    .fetchnext1
  1434. .positive1    move.b    d2,-(a0)        ; store LO and HI value
  1435.         move.b    d1,-(a0)
  1436.         sub.l    d5,d6            ; stretch the table
  1437.         bpl.s    .repeat1        ; to 32768 entries
  1438.         add.l    #32768,d6
  1439.         subq.w    #1,d2            ; decrement lo value
  1440.         subq.w    #1,d3            ; decrement counter
  1441. .repeat1    dbra    d0,.outerloop1
  1442.  
  1443.         movem.l    (sp)+,a2/d2-d6
  1444.         rts
  1445.  
  1446.  
  1447. ****** [driver].audio/AHIsub_FreeAudio **************************************
  1448. *
  1449. *   NAME
  1450. *       AHIsub_FreeAudio -- Deallocates the audio hardware.
  1451. *
  1452. *   SYNOPSIS
  1453. *       AHIsub_FreeAudio( audioctrl );
  1454. *                         A2
  1455. *
  1456. *       void AHIsub_FreeAudio( struct AHIAudioCtrlDrv * );
  1457. *
  1458. *   IMPLEMENTATION
  1459. *       Deallocate the audio hardware and other resources allocated in
  1460. *       AHIsub_AllocAudio(). AHIsub_Stop() will always be called by
  1461. *       'ahi.device' before this call is made.
  1462. *
  1463. *   INPUTS
  1464. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1465. *
  1466. *   NOTES
  1467. *       It must be safe to call this routine even if AHIsub_AllocAudio()
  1468. *       was never called, failed or called more than once.
  1469. *
  1470. *   SEE ALSO
  1471. *       AHIsub_AllocAudio()
  1472. *
  1473. *****************************************************************************
  1474. *
  1475. *
  1476.  
  1477. AHIsub_FreeAudio:
  1478.     PRINTF    2,"AHIsub_FreeAudio()"
  1479.     pushm    std
  1480.  
  1481.     move.l    a6,a5
  1482.     move.l    pb_SysLib(a5),a6
  1483.  
  1484.     move.l    ahiac_DriverData(a2),d0
  1485.     beq    .nopaula
  1486.     move.l    d0,a3
  1487.  
  1488.     move.l    p_Sounds(a3),d0
  1489.     beq.b    .nosounds
  1490.     move.l    d0,a1
  1491.     call    FreeVec
  1492. .nosounds
  1493.  
  1494.     move.l    p_CalibrationTable(a3),d0
  1495.     beq.b    .notable
  1496.     move.l    d0,a1
  1497.     call    FreeVec
  1498. .notable
  1499.  
  1500.     tst.b    p_Filter(a3)
  1501.     beq    .no_filter
  1502.     bclr    #1,$bfe001            ;turn audio filter on
  1503.     bra    .filter_set
  1504. .no_filter
  1505.     bset    #1,$bfe001            ;turn audio filter off
  1506. .filter_set
  1507.  
  1508.  
  1509.     tst.l    p_audiodev(a3)
  1510.     bne.b    .noaudiodev
  1511.     move.l    p_audioreq(a3),a1
  1512.     move.w    #CMD_RESET,IO_COMMAND(a1)    ;Restore audio interrupts
  1513.     bsr.w    BeginIO
  1514.     move.l    p_audioport(a3),a0
  1515.     call    WaitPort
  1516.     move.l    p_audioport(a3),a0
  1517.     call    GetMsg
  1518.     move.l    p_audioreq(a3),a1
  1519.     subq.l    #1,p_audiodev(a3)
  1520.     call    CloseDevice
  1521. .noaudiodev
  1522.     move.l    p_audioreq(a3),d0
  1523.     beq.b    .noaudioreq
  1524.     move.l    d0,a1
  1525.     call    FreeVec
  1526. .noaudioreq
  1527.     move.l    p_audioport(a3),d0
  1528.     beq.b    .noaudioport
  1529.     move.l    d0,a0
  1530.     call    DeleteMsgPort
  1531. .noaudioport
  1532.     tst.l    p_AuraAddress(a3)
  1533.     beq    .noaura
  1534.     move.l    pb_CardResource(a5),d0
  1535.     beq    .noaura
  1536.     move.l    d0,a6
  1537.     move.l    p_CardHandle(a3),d0
  1538.     beq    .noaura
  1539.     move.l    d0,a1
  1540.     call    EndCardAccess
  1541.     move.l    p_CardHandle(a3),a1
  1542.     moveq    #CARDF_REMOVEHANDLE,d0
  1543.     call    ReleaseCard
  1544. .noaura
  1545.     move.l    pb_SysLib(a5),a6
  1546.     move.l    p_CardHandle(a3),d0
  1547.     beq    .nocardhandle
  1548.     move.l    d0,a1
  1549.     call    FreeVec
  1550. .nocardhandle
  1551.     move.l    pb_MiscResource(a5),a6
  1552.     tst.l    p_ParPortUser(a3)
  1553.     bne.b    .noparport
  1554.     moveq    #MR_PARALLELPORT,d0
  1555.     jsr    MR_FREEMISCRESOURCE(a6)
  1556. .noparport
  1557.     tst.l    p_ParBitsUser(a3)
  1558.     bne.b    .noparbits
  1559.     moveq    #MR_PARALLELBITS,d0
  1560.     jsr    MR_FREEMISCRESOURCE(a6)
  1561. .noparbits
  1562.     tst.l    p_SerBitsUser(a3)
  1563.     bne.b    .noserbits
  1564.     moveq    #MR_SERIALBITS,d0
  1565.     jsr    MR_FREEMISCRESOURCE(a6)
  1566. .noserbits
  1567.     move.l    pb_SysLib(a5),a6
  1568.     move.l    a3,a1
  1569.     clr.l    ahiac_DriverData(a2)
  1570.     call    FreeVec
  1571. .nopaula
  1572.     moveq    #0,d0
  1573.     popm    std
  1574.     rts
  1575.  
  1576.  
  1577. ****** [driver].audio/AHIsub_Disable ****************************************
  1578. *
  1579. *   NAME
  1580. *       AHIsub_Disable -- Temporary turn off audio interrupt/task
  1581. *
  1582. *   SYNOPSIS
  1583. *       AHIsub_Disable( audioctrl );
  1584. *                       A2
  1585. *
  1586. *       void AHIsub_Disable( struct AHIAudioCtrlDrv * );
  1587. *
  1588. *   IMPLEMENTATION
  1589. *       If you are lazy, then call exec.library/Disable().
  1590. *       If you are smart, only disable your own interrupt or task.
  1591. *
  1592. *   INPUTS
  1593. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1594. *
  1595. *   NOTES
  1596. *       This call should be guaranteed to preserve all registers.
  1597. *       This call nests.
  1598. *
  1599. *   SEE ALSO
  1600. *       AHIsub_Enable(), exec.library/Disable()
  1601. *
  1602. *****************************************************************************
  1603. *
  1604. * MUST NOT REFERENCE a6!! (See PlayerFunc()!)
  1605. *
  1606.  
  1607. AHIsub_Disable:
  1608.     PRINTF    4,"AHIsub_Disable()"
  1609.     push    a3
  1610.     move.l    ahiac_DriverData(a2),a3
  1611.     addq.w    #1,p_DisableCount(a3)
  1612.     move.w    #INTF_AUDIO,custom+INTENA  ; Turn off ALL audio interrupts
  1613.     pop    a3
  1614.     rts
  1615.  
  1616.  
  1617. ****** [driver].audio/AHIsub_Enable *****************************************
  1618. *
  1619. *   NAME
  1620. *       AHIsub_Enable -- Turn on audio interrupt/task
  1621. *
  1622. *   SYNOPSIS
  1623. *       AHIsub_Enable( audioctrl );
  1624. *                      A2
  1625. *
  1626. *       void AHIsub_Enable( struct AHIAudioCtrlDrv * );
  1627. *
  1628. *   IMPLEMENTATION
  1629. *       If you are lazy, then call exec.library/Enable().
  1630. *       If you are smart, only enable your own interrupt or task.
  1631. *
  1632. *   INPUTS
  1633. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1634. *
  1635. *   NOTES
  1636. *       This call should be guaranteed to preserve all registers.
  1637. *       This call nests.
  1638. *
  1639. *   SEE ALSO
  1640. *       AHIsub_Disable(), exec.library/Enable()
  1641. *
  1642. *****************************************************************************
  1643. *
  1644. * MUST NOT REFERENCE a6!! (See PlayerFunc()!)
  1645. *
  1646.  
  1647. AHIsub_Enable:
  1648.     PRINTF    4,"AHIsub_Enable()"
  1649.     push    a3
  1650.     move.l    ahiac_DriverData(a2),a3
  1651.     subq.w    #1,p_DisableCount(a3)
  1652.     bne    .exit
  1653.     move.w    p_IRQMask(a3),custom+INTENA
  1654. .exit
  1655.     pop    a3
  1656.     rts
  1657.  
  1658.  
  1659. ****** [driver].audio/AHIsub_Start ******************************************
  1660. *
  1661. *   NAME
  1662. *       AHIsub_Start -- Starts playback or recording
  1663. *
  1664. *   SYNOPSIS
  1665. *       error = AHIsub_Start( flags, audioctrl );
  1666. *       D0                    D0     A2
  1667. *
  1668. *       ULONG AHIsub_Start(ULONG, struct AHIAudioCtrlDrv * );
  1669. *
  1670. *   IMPLEMENTATION
  1671. *       What to do depends what you returned in AHIsub_AllocAudio().
  1672. *
  1673. *     * First, assume bit AHISB_PLAY in flags is set. This means that you
  1674. *       should begin playback.
  1675. *
  1676. *     - AHIsub_AllocAudio() returned AHISF_MIXING|AHISF_TIMING:
  1677. *
  1678. *       A) Allocate a mixing buffer of ahiac_BuffSize bytes. The buffer must
  1679. *          be long aligned!
  1680. *       B) Create/start an interrupt or task that will do 1-6 over and over
  1681. *          again until AHIsub_Stop() is called. Note that it is not a good
  1682. *          idea to do the actual mixing and conversion in a real hardware
  1683. *          interrupt. Signal a task or create a Software Interrupt to do
  1684. *          the number crunching.
  1685. *
  1686. *       1) Call the user Hook ahiac_PlayerFunc with the following parameters:
  1687. *                  A0 - (struct Hook *)
  1688. *                  A2 - (struct AHIAudioCtrlDrv *)
  1689. *                  A1 - Set to NULL.
  1690. *
  1691. *       2) [Call the ahiac_PreTimer function. If it returns TRUE (Z will be
  1692. *          cleared so you don't have to test d0), skip step 3 and 4. This
  1693. *          is used to avoid overloading the CPU. This step is optional.
  1694. *          A2 is assumed to point to struct AHIAudioCtrlDrv. All registers
  1695. *          except d0 are preserved.  (V4)]
  1696. *
  1697. *       3) Call the mixing Hook (ahiac_MixerFunc) with the following
  1698. *          parameters:
  1699. *                  A0 - (struct Hook *)           - The Hook itself
  1700. *                  A2 - (struct AHIAudioCtrlDrv *)
  1701. *                  A1 - (WORD *[])                - The mixing buffer.
  1702. *          Note that ahiac_MixerFunc preserves ALL registers.
  1703. *          The user Hook ahiac_SoundFunc will be called by the mixing
  1704. *          routine when a sample have been processed, so you don't have to
  1705. *          worry about that.
  1706. *          How the buffer will be filled is indicated by ahiac_Flags.
  1707. *          It is always filled with signed 16-bit (32 bit if AHIACB_HIFI in
  1708. *          in ahiac_Flags is set) words, even if playback is 8 bit. If
  1709. *          AHIDBB_STEREO is set (in ahiac_Flags), data for left and right
  1710. *          channel are interleaved:
  1711. *           1st sample left channel,
  1712. *           1st sample right channel,
  1713. *           2nd sample left channel,
  1714. *           ...,
  1715. *           ahiac_BuffSamples:th sample left channel,
  1716. *           ahiac_BuffSamples:th sample right channel.
  1717. *          If AHIDBB_STEREO is cleared, the mono data is stored:
  1718. *           1st sample,
  1719. *           2nd sample,
  1720. *           ...,
  1721. *           ahiac_BuffSamples:th sample.
  1722. *          Note that neither AHIACB_STEREO nor AHIACB_HIFI will be set if
  1723. *          you didn't report that you understand these flags when
  1724. *          AHI_AllocAudio() was called.
  1725. *
  1726. *          For AHI V2, the type of buffer is also available in ahiac_BuffType.
  1727. *          It is suggested that you use this value instead. ahiac_BuffType
  1728. *          can be one of AHIST_M16S, AHIST_S16S, AHIST_M32S and AHIST_S32S.
  1729. *
  1730. *       4) Convert the buffer if needed and feed it to the audio hardware.
  1731. *          Note that you may have to clear CPU caches if you are using DMA
  1732. *          to play the buffer, and the buffer is not allocated in non-
  1733. *          cachable RAM.
  1734. *
  1735. *       5) [Call the ahiac_PostTimer function. A2 is assumed to point to
  1736. *          struct AHIAudioCtrlDrv. All registers are preserved.  (V4)]
  1737. *
  1738. *       6) Wait until the whole buffer has been played, then repeat.
  1739. *
  1740. *       Use double buffering if possible!
  1741. *
  1742. *       You may DECREASE ahiac_BuffSamples slightly, for example to force an
  1743. *       even number of samples to be mixed. By doing this you will make
  1744. *       ahiac_PlayerFunc to be called at wrong frequency so be careful!
  1745. *       Even if ahiac_BuffSamples is defined ULONG, it will never be greater
  1746. *       than 65535.
  1747. *
  1748. *       ahiac_BuffSize is the largest size of the mixing buffer that will be
  1749. *       needed until AHIsub_Stop() is called.
  1750. *
  1751. *       ahiac_MaxBuffSamples is the maximum number of samples that will be
  1752. *       mixed (until AHIsub_Stop() is called). You can use this value if you
  1753. *       need to allocate DMA buffers.
  1754. *
  1755. *       ahiac_MinBuffSamples is the minimum number of samples that will be
  1756. *       mixed. Most drivers will ignore it.
  1757. *
  1758. *       If AHIsub_AllocAudio() returned with the AHISB_CANPOSTPROCESS bit set,
  1759. *       ahiac_BuffSize is large enough to hold two buffers. The mixing buffer
  1760. *       will be filled with the wet buffer first, immediately followed by the
  1761. *       dry buffer. I.e., ahiac_BuffSamples sample frames wet data, then
  1762. *       ahiac_BuffSamples sample frames dry data. The DSP fx should only be
  1763. *       applied to the wet buffer, and the two buffers should then be added
  1764. *       together. (V4)
  1765. *
  1766. *     - If AHIsub_AllocAudio() returned AHISF_MIXING, do as described above,
  1767. *       except calling ahiac_PlayerFunc. ahiac_PlayerFunc should be called
  1768. *       ahiac_PlayerFreq times per second, clocked by timers on your sound
  1769. *       card or by using 'timer.device' or 'realtime.library'. No other Amiga
  1770. *       resources may be used for timing (like direct CIA timers).
  1771. *       ahiac_MinBuffSamples and ahiac_MaxBuffSamples are undefined if
  1772. *       AHIsub_AllocAudio() returned AHISF_MIXING (AHISB_TIMING bit not set).
  1773. *
  1774. *     - If AHIsub_AllocAudio() returned with neither the AHISB_MIXING nor
  1775. *       the AHISB_TIMING bit set, then just start playback. Don't forget to
  1776. *       call ahiac_PlayerFunc ahiac_PlayerFreq times per second. Only your
  1777. *       own timing hardware, 'timer.device'  or 'realtime.library' may be
  1778. *       used. Note that ahiac_MixerFunc, ahiac_BuffSamples,
  1779. *       ahiac_MinBuffSamples, ahiac_MaxBuffSamples and ahiac_BuffSize are
  1780. *       undefined. ahiac_MixFreq is the frequency the user wants to use for
  1781. *       recording, if you support that.
  1782. *
  1783. *     * Second, assume bit AHISB_RECORD in flags is set. This means that you
  1784. *       should start to sample. Create a interrupt or task that does the
  1785. *       following:
  1786. *
  1787. *       Allocate a buffer (you chose size, but try to keep it reasonable
  1788. *       small to avoid delays - it is suggested that RecordFunc is called
  1789. *       at least 4 times/second for the lowers sampling rate, and more often
  1790. *       for higher rates), and fill it with the sampled data. The buffer must
  1791. *       be long aligned, and it's size must be evenly divisible by four.
  1792. *       The format should always be AHIST_S16S (even with 8 bit mono samplers),
  1793. *       which means:
  1794. *           1st sample left channel,
  1795. *           1st sample right channel (same as prev. if mono),
  1796. *           2nd sample left channel,
  1797. *           ... etc.
  1798. *       Each sample is a signed word (WORD). The sample rate should be equal
  1799. *       to the mixing rate.
  1800. *
  1801. *       Call the ahiac_SamplerFunc Hook with the following parameters:
  1802. *           A0 - (struct Hook *)           - The Hook itself
  1803. *           A2 - (struct AHIAudioCtrlDrv *)
  1804. *           A1 - (struct AHIRecordMessage *)
  1805. *       The message should be filled as follows:
  1806. *           ahirm_Type - Set to AHIST_S16S.
  1807. *           ahirm_Buffer - A pointer to the filled buffer.
  1808. *           ahirm_Samples - How many sample frames stored.
  1809. *       You must not destroy the buffer until next time the Hook is called.
  1810. *
  1811. *       Repeat until AHIsub_Stop() is called.
  1812. *
  1813. *     * Note that both bits may be set when this function is called.
  1814. *
  1815. *   INPUTS
  1816. *       flags - See <libraries/ahi_sub.h>.
  1817. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1818. *
  1819. *   RESULT
  1820. *       Returns AHIE_OK if successful, else an error code as defined
  1821. *       in <devices/ahi.h>. AHIsub_Stop() will always be called, even
  1822. *       if this call failed.
  1823. *
  1824. *   NOTES
  1825. *       The driver must be able to handle multiple calls to this routine
  1826. *       without preceding calls to AHIsub_Stop().
  1827. *
  1828. *   SEE ALSO
  1829. *       AHIsub_Update(), AHIsub_Stop()
  1830. *
  1831. *****************************************************************************
  1832. *
  1833. *
  1834. *
  1835.  
  1836. AHIsub_Start:
  1837.     PRINTF    2,"AHIsub_Start()"
  1838.  
  1839.     pushm    std
  1840.  
  1841.     move.l    d0,d7
  1842.     lea    custom,a4
  1843.     move.l    ahiac_DriverData(a2),a3
  1844.  
  1845.     btst    #AHISB_PLAY,d7
  1846.     beq    .dont_play
  1847.  
  1848. **
  1849. *** AHISB_PLAY
  1850. **
  1851.     moveq    #AHISF_PLAY,d0
  1852.     call    AHIsub_Stop            ;Stop current playback if any.
  1853.     call    AHIsub_Update            ;fill variables
  1854.  
  1855.     move.l    a6,a5
  1856.     move.l    pb_SysLib(a5),a6
  1857.  
  1858.     btst    #PB_DMA,p_Flags(a3)
  1859.     beq    .no_dma
  1860.     bsr    DMA_Start
  1861.     bra    .exit
  1862. .no_dma
  1863.  
  1864.     move.l    ahiac_BuffSize(a2),d0
  1865.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  1866.     call    AllocVec
  1867.     move.l    d0,p_Mixbuffer(a3)
  1868.     beq    .error_nomem
  1869.  
  1870.     move.l    ahiac_MixFreq(a2),d1
  1871.     bsr.w    calcperiod
  1872.     move.w    d1,p_AudPer(a3)
  1873.  
  1874. * The init*bit?  routines allocates p_DMAbuffer, sets up
  1875. * p_AudPtr, sets the volume, stores the correct interrupt routines in
  1876. * p_PlayInt's and p_PlaySoftInt's IS_CODE.
  1877.  
  1878.     pea    .1(pc)
  1879.     move.b    p_Flags(a3),d0
  1880.     and.b    #PF_STEREO|PF_14BIT,d0
  1881.     beq.w    init8bitM
  1882.     cmp.b    #PF_STEREO,d0
  1883.     beq.w    init8bitS
  1884.     cmp.b    #PF_14BIT,d0
  1885.     beq.w    init14bitM
  1886.     bra.w    init14bitS
  1887. .1
  1888.     tst.l    d0
  1889.     bne    .exit
  1890.  
  1891. * Install play interrupt
  1892.     lea    p_PlayInt(a3),a1
  1893.     moveq    #INTB_AUD0,d0
  1894.     call    SetIntVector
  1895.     clr.w    p_DisableCount(a3)
  1896.  
  1897.     or.w    #INTF_SETCLR|INTF_AUD0,p_IRQMask(a3)
  1898.     move.w    #INTF_SETCLR|INTF_AUD0,INTENA(a4)    ;enable
  1899.     move.w    #INTF_SETCLR|INTF_AUD0,INTREQ(a4)    ;start
  1900.  
  1901.     move.l    a5,a6
  1902.  
  1903.  
  1904. .dont_play
  1905.     btst    #AHISB_RECORD,d7
  1906.     beq    .dont_record
  1907. **
  1908. *** AHISB_RECORD
  1909. **
  1910.     moveq    #0,d0
  1911.     move.b    p_Flags(a3),d0            ;Sanity check...
  1912.     and.b    #PF_14BIT|PF_DMA,d0
  1913.     bne    .error_unknown
  1914.  
  1915.     moveq    #AHISF_RECORD,d0
  1916.     call    AHIsub_Stop            ;Stop current recording if any.
  1917.  
  1918.     move.l    a6,a5
  1919.     move.l    pb_SysLib(a5),a6
  1920.  
  1921.     move.l    #RECORDSAMPLES*4,d0
  1922.     move.l    #MEMF_PUBLIC,d1
  1923.     call    AllocVec
  1924.     move.l    d0,p_RecBuffer1(a3)
  1925.     beq    .error_nomem
  1926.  
  1927.     move.l    d0,p_RecFillPtr(a3)
  1928.     move.w    #RECORDSAMPLES,p_RecFillCount(a3)
  1929.  
  1930.     move.l    #RECORDSAMPLES*4,d0
  1931.     move.l    #MEMF_PUBLIC,d1
  1932.     call    AllocVec
  1933.     move.l    d0,p_RecBuffer2(a3)
  1934.     beq    .error_nomem
  1935.  
  1936.     move.l    ahiac_MixFreq(a2),d1
  1937.     bsr.w    calcperiod
  1938.     lsr.w    #1,d1                ;Period/2 => Frequency·2
  1939.     move.w    d1,AUD2PER(a4)
  1940.     move.w    d1,AUD3PER(a4)
  1941.     move.w    p_MonitorVolume(a3),d0
  1942.     move.w    d0,AUD2VOL(a4)
  1943.     move.w    d0,AUD3VOL(a4)
  1944.  
  1945. * Install record interrupt
  1946.     move.w    p_Input(a3),d0
  1947.     beq    .parsampler
  1948.     cmp.w    #1,d0
  1949.     beq    .aurasampler
  1950.     cmp.w    #2,d0
  1951.     beq    .clarity
  1952.     bra    .error_unknown
  1953.  
  1954. .parsampler
  1955.     tst.b    p_Parallel(a3)            ;Parrallel port allocated?
  1956.     beq    .error_unknown
  1957.     lea    p_RecIntData(a3),a1
  1958.     move.l    a1,IS_DATA+p_RecInt(a3)
  1959.     move.l    #RecordInterrupt,IS_CODE+p_RecInt(a3)
  1960.  
  1961.     move.b    #$ff,_ciab+ciaddrb        ; Set parallel port to output
  1962.  
  1963.     bra    .setrecint
  1964.  
  1965. .clarity
  1966.     tst.b    p_Parallel(a3)            ;Parrallel port allocated?
  1967.     beq    .error_unknown
  1968.  
  1969.     move.l    pb_MiscResource(a5),a6
  1970.     move.l    #MR_SERIALBITS,d0    ; allocate serial port control lines
  1971.     lea    IDString(pc),a1
  1972.     jsr    MR_ALLOCMISCRESOURCE(a6)
  1973.     move.l    d0,p_SerBitsUser(a3)
  1974.     bne    .error_unknown
  1975.  
  1976.     lea    p_RecIntData(a3),a1
  1977.     move.l    a1,IS_DATA+p_RecInt(a3)
  1978.     move.l    #RecordInterruptClarity,IS_CODE+p_RecInt(a3)
  1979.  
  1980.     ; Set DTR, PRTBUSY and PRTRPOUT to outputs
  1981.     or.b    #CIAF_COMDTR!CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciaddra
  1982.     move.b    #$ff,_ciab+ciaddrb        ; Set parallel port to output
  1983.     ; Reset Clarity
  1984.     move.b    #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
  1985.     move.b    #CIAF_PRTRPOUT,_ciab+ciapra
  1986.     move.b    #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
  1987.     ; Clarity is now in stereo record mode
  1988.  
  1989.     bra    .setrecint
  1990.  
  1991. .aurasampler
  1992.     tst.l    p_AuraAddress(a3)        ;Aura sampler allocated?
  1993.     beq    .error_unknown
  1994.     lea    p_RecIntDataAura(a3),a1
  1995.     move.l    a1,IS_DATA+p_RecInt(a3)
  1996.     move.l    #RecordInterruptAura,IS_CODE+p_RecInt(a3)
  1997.     bra    .setrecint
  1998.  
  1999. .setrecint
  2000.     move.l    pb_SysLib(a5),a6
  2001.     lea    p_RecInt(a3),a1
  2002.     moveq    #INTB_AUD3,d0
  2003.     call    SetIntVector
  2004.  
  2005.     move.w    #DMAF_AUD2|DMAF_AUD3,DMACON(a4)        ;disable DMA
  2006.     or.w    #INTF_SETCLR|INTF_AUD3,p_IRQMask(a3)
  2007.     move.w    #INTF_SETCLR|INTF_AUD3,INTENA(a4)    ;enable
  2008.     move.w    #INTF_SETCLR|INTF_AUD3,INTREQ(a4)    ;start
  2009.  
  2010. .dont_record
  2011. .return
  2012.     moveq    #AHIE_OK,d0
  2013. .exit
  2014.     popm    std
  2015.     rts
  2016. .error_nomem
  2017.     moveq    #AHIE_NOMEM,d0
  2018.     bra.b    .exit
  2019. .error_unknown
  2020.     moveq    #AHIE_UNKNOWN,d0
  2021.     bra.b    .exit
  2022.  
  2023.  
  2024. ;in:
  2025. * a2    AudioCtrl
  2026. * a3    paula
  2027. * a4    custom
  2028. * a5    paulaBase
  2029. * a6    ExecBase
  2030. init8bitM:
  2031.     PRINTF    2,"init8bitM()"
  2032.     move.l    #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
  2033.     move.l    #SoftInt_8bitM,IS_CODE+p_PlaySoftInt(a3)
  2034.     move.b    p_Flags(a3),d0
  2035.     btst    #PB_HIFI,d0
  2036.     beq    .nohifi
  2037.     move.l    #SoftInt_8bitMH,IS_CODE+p_PlaySoftInt(a3)
  2038. .nohifi
  2039.  
  2040.     move.l    p_MinBufferLength(a3),d0
  2041.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 8 bit samples
  2042.     addq.l    #3,d0
  2043.     and.b    #~3,d0                ;make it a multiple of 4
  2044.     move.l    d0,d2                ;d2 = channel size
  2045.  
  2046.     lsl.l    #1,d0                ;Double buffer
  2047.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  2048.     call    AllocVec
  2049.     move.l    d0,p_DMAbuffer(a3)
  2050.     beq    .nomem
  2051.  
  2052.     move.l    d0,p_AudPtr1A(a3)
  2053.     move.l    d0,p_AudPtr2A(a3)
  2054.     add.l    d2,d0
  2055.     move.l    d0,p_AudPtr1B(a3)
  2056.     move.l    d0,p_AudPtr2B(a3)
  2057.  
  2058. ;    move.w    #64,AUD0VOL(a4)
  2059. ;    move.w    #64,AUD1VOL(a4)
  2060.  
  2061.     moveq    #0,d0
  2062.     rts
  2063. .nomem
  2064.     moveq    #AHIE_NOMEM,d0
  2065.     rts
  2066.  
  2067. ;in:
  2068. * a2    AudioCtrl
  2069. * a3    paula
  2070. * a5    paulaBase
  2071. * a6    ExecBase
  2072. init8bitS:
  2073.     PRINTF    2,"init8bitS()"
  2074.     move.l    #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
  2075.     move.l    #SoftInt_8bitS,IS_CODE+p_PlaySoftInt(a3)
  2076.     move.b    p_Flags(a3),d0
  2077.     btst    #PB_HIFI,d0
  2078.     beq    .nohifi
  2079.     move.l    #SoftInt_8bitSH,IS_CODE+p_PlaySoftInt(a3)
  2080. .nohifi
  2081.  
  2082.     move.l    p_MinBufferLength(a3),d0
  2083.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 8 bit samples
  2084.     addq.l    #3,d0
  2085.     and.b    #~3,d0                ;make it a multiple of 4
  2086.     move.l    d0,d2                ;d2 = channel size
  2087.  
  2088.     lsl.l    #2,d0                ;Double buffer + Stereo
  2089.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  2090.     call    AllocVec
  2091.     move.l    d0,p_DMAbuffer(a3)
  2092.     beq    .nomem
  2093.  
  2094.     move.l    d0,p_AudPtr1A(a3)
  2095.     add.l    d2,d0
  2096.     move.l    d0,p_AudPtr2A(a3)
  2097.     add.l    d2,d0
  2098.     move.l    d0,p_AudPtr1B(a3)
  2099.     add.l    d2,d0
  2100.     move.l    d0,p_AudPtr2B(a3)
  2101.  
  2102. ;    move.w    #64,AUD0VOL(a4)
  2103. ;    move.w    #64,AUD1VOL(a4)
  2104.  
  2105.     moveq    #0,d0
  2106.     rts
  2107. .nomem
  2108.     moveq    #AHIE_NOMEM,d0
  2109.     rts
  2110.  
  2111. ;in:
  2112. * a2    AudioCtrl
  2113. * a3    paula
  2114. * a5    paulaBase
  2115. * a6    ExecBase
  2116. init14bitM:
  2117.     PRINTF    2,"init14bitM()"
  2118.     move.l    #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
  2119.     lea    SoftInt_14bitM(pc),a0
  2120.     move.b    p_Flags(a3),d0
  2121.     btst    #PB_HIFI,d0
  2122.     beq    .nohifi1
  2123.     lea    SoftInt_14bitMH(pc),a0
  2124. .nohifi1
  2125.     tst.l    p_CalibrationTable(a3)
  2126.     beq.b    .nocalib
  2127.     lea    SoftInt_14CbitM(pc),a0
  2128.     move.b    p_Flags(a3),d0
  2129.     btst    #PB_HIFI,d0
  2130.     beq    .nohifi2
  2131.     lea    SoftInt_14CbitMH(pc),a0
  2132. .nohifi2
  2133. .nocalib
  2134.     move.l    a0,IS_CODE+p_PlaySoftInt(a3)
  2135.  
  2136.     move.l    p_MinBufferLength(a3),d0
  2137.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 16 bit samples
  2138.     addq.l    #3,d0
  2139.     and.b    #~3,d0                ;make it a multiple of 4
  2140.     move.l    d0,d2                ;d2 = channel size
  2141.  
  2142.     lsl.l    #2,d0                ;Double buffer + 2×8 bit
  2143.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  2144.     call    AllocVec
  2145.     move.l    d0,p_DMAbuffer(a3)
  2146.     beq    .nomem
  2147.  
  2148.     move.l    d0,p_AudPtr1A(a3)
  2149.     move.l    d0,p_AudPtr2A(a3)
  2150.     add.l    d2,d0
  2151.     move.l    d0,p_AudPtr4A(a3)
  2152.     move.l    d0,p_AudPtr3A(a3)
  2153.     add.l    d2,d0
  2154.     move.l    d0,p_AudPtr1B(a3)
  2155.     move.l    d0,p_AudPtr2B(a3)
  2156.     add.l    d2,d0
  2157.     move.l    d0,p_AudPtr4B(a3)
  2158.     move.l    d0,p_AudPtr3B(a3)
  2159.  
  2160. ;    move.w    #64,AUD0VOL(a4)
  2161. ;    move.w    #64,AUD1VOL(a4)
  2162. ;    move.w    #1,AUD2VOL(a4)
  2163. ;    move.w    #1,AUD3VOL(a4)
  2164.  
  2165.     moveq    #0,d0
  2166.     rts
  2167. .nomem
  2168.     moveq    #AHIE_NOMEM,d0
  2169.     rts
  2170.  
  2171. ;in:
  2172. * a2    AudioCtrl
  2173. * a3    paula
  2174. * a5    paulaBase
  2175. * a6    ExecBase
  2176. init14bitS:
  2177.     PRINTF    2,"init14bitS()"
  2178.     move.l    #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
  2179.     lea    SoftInt_14bitS(pc),a0
  2180.     move.b    p_Flags(a3),d0
  2181.     btst    #PB_HIFI,d0
  2182.     beq    .nohifi1
  2183.     lea    SoftInt_14bitSH(pc),a0
  2184. .nohifi1
  2185.     tst.l    p_CalibrationTable(a3)
  2186.     beq.b    .nocalib
  2187.     lea    SoftInt_14CbitS(pc),a0
  2188.     move.b    p_Flags(a3),d0
  2189.     btst    #PB_HIFI,d0
  2190.     beq    .nohifi2
  2191.     lea    SoftInt_14CbitSH(pc),a0
  2192. .nohifi2
  2193. .nocalib
  2194.     move.l    a0,IS_CODE+p_PlaySoftInt(a3)
  2195.  
  2196.     move.l    p_MinBufferLength(a3),d0
  2197.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 16 bit samples
  2198.     addq.l    #3,d0
  2199.     and.b    #~3,d0                ;make it a multiple of 4
  2200.     move.l    d0,d2                ;d2 = channel size
  2201.  
  2202.     lsl.l    #3,d0                ;Double buffer + 2×8 bit + Stereo
  2203.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  2204.     call    AllocVec
  2205.     move.l    d0,p_DMAbuffer(a3)
  2206.     beq    .nomem
  2207.  
  2208.     move.l    d0,p_AudPtr1A(a3)
  2209.     add.l    d2,d0
  2210.     move.l    d0,p_AudPtr2A(a3)
  2211.     add.l    d2,d0
  2212.     move.l    d0,p_AudPtr3A(a3)
  2213.     add.l    d2,d0
  2214.     move.l    d0,p_AudPtr4A(a3)
  2215.     add.l    d2,d0
  2216.     move.l    d0,p_AudPtr1B(a3)
  2217.     add.l    d2,d0
  2218.     move.l    d0,p_AudPtr2B(a3)
  2219.     add.l    d2,d0
  2220.     move.l    d0,p_AudPtr3B(a3)
  2221.     add.l    d2,d0
  2222.     move.l    d0,p_AudPtr4B(a3)
  2223.  
  2224. ;    move.w    #64,AUD0VOL(a4)
  2225. ;    move.w    #64,AUD1VOL(a4)
  2226. ;    move.w    #1,AUD2VOL(a4)
  2227. ;    move.w    #1,AUD3VOL(a4)
  2228.  
  2229.     moveq    #0,d0
  2230.     rts
  2231. .nomem
  2232.     moveq    #AHIE_NOMEM,d0
  2233.     rts
  2234.  
  2235.  
  2236. ****** [driver].audio/AHIsub_Update *****************************************
  2237. *
  2238. *   NAME
  2239. *       AHIsub_Update -- Update some variables
  2240. *
  2241. *   SYNOPSIS
  2242. *       AHIsub_Update( flags, audioctrl );
  2243. *                      D0     A2
  2244. *
  2245. *       void AHIsub_Update(ULONG, struct AHIAudioCtrlDrv * );
  2246. *
  2247. *   IMPLEMENTATION
  2248. *       All you have to do is to update some variables:
  2249. *
  2250. *     * Mixing & timing: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc,
  2251. *       ahiac_BuffSamples (and perhaps ahiac_PlayerFreq if you use it).
  2252. *
  2253. *     * Mixing only: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc and
  2254. *           ahiac_PlayerFreq.
  2255. *
  2256. *     * Nothing: ahiac_PlayerFunc, ahiac_SamplerFunc and ahiac_PlayerFreq.
  2257. *
  2258. *   INPUTS
  2259. *       flags - Currently no flags defined.
  2260. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  2261. *
  2262. *   RESULT
  2263. *
  2264. *   NOTES
  2265. *       This call must be safe from interrupts.
  2266. *
  2267. *   SEE ALSO
  2268. *       AHIsub_Start()
  2269. *
  2270. *****************************************************************************
  2271. *
  2272. *
  2273. *
  2274.  
  2275. AHIsub_Update:
  2276.     PRINTF    2,"AHIsub_Update()"
  2277.     pushm    std
  2278.  
  2279.     call    AHIsub_Disable        ;make sure we don't get an interrupt
  2280.                     ;while updating our local variables
  2281.     move.l    ahiac_DriverData(a2),a3
  2282.  
  2283.     move.l    ahiac_PlayerFunc(a2),a0
  2284.     move.l    a0,p_PlayerHook(a3)
  2285.     move.l    h_Entry(a0),p_PlayerEntry(a3)
  2286.  
  2287.     btst    #PB_DMA,p_Flags(a3)
  2288.     beq    .no_dma
  2289.     bsr    DMA_Update
  2290.     bra    .exit
  2291.  
  2292. .no_dma
  2293.     move.l    ahiac_BuffSamples(a2),d1
  2294.     and.b    #~3,d1            ;make it a multiple of 4
  2295.     move.l    d1,ahiac_BuffSamples(a2)
  2296.     move.l    d1,d0
  2297.     lsr.l    #2,d0
  2298.     subq.l    #1,d0
  2299.     move.l    d0,p_LoopTimes(a3)    ;See softints. (Unrolled)
  2300.  
  2301.     move.l    ahiac_MixerFunc(a2),a0
  2302.     move.l    a0,p_MixHook(a3)
  2303.     move.l    h_Entry(a0),p_MixEntry(a3)
  2304.  
  2305. .exit
  2306.     call    AHIsub_Enable
  2307.     moveq    #0,d0
  2308.     popm    std
  2309.     rts
  2310.  
  2311.  
  2312. ****** [driver].audio/AHIsub_Stop *******************************************
  2313. *
  2314. *   NAME
  2315. *       AHIsub_Stop -- Stops playback.
  2316. *
  2317. *   SYNOPSIS
  2318. *       AHIsub_Stop( flags, audioctrl );
  2319. *                    D0     A2
  2320. *
  2321. *       void AHIsub_Stop( ULONG, struct AHIAudioCtrlDrv * );
  2322. *
  2323. *   IMPLEMENTATION
  2324. *       Stop playback and/or recording, remove all resources allocated by
  2325. *       AHIsub_Start().
  2326. *
  2327. *   INPUTS
  2328. *       flags - See <libraries/ahi_sub.h>.
  2329. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  2330. *
  2331. *   NOTES
  2332. *       It must be safe to call this routine even if AHIsub_Start() was never
  2333. *       called, failed or called more than once.
  2334. *
  2335. *   SEE ALSO
  2336. *       AHIsub_Start()
  2337. *
  2338. *****************************************************************************
  2339. *
  2340. *
  2341.  
  2342. AHIsub_Stop:
  2343.     PRINTF    2,"AHIsub_Stop()"
  2344.     pushm    std
  2345.  
  2346.     lea    custom,a4
  2347.     move.l    a6,a5
  2348.     move.l    pb_SysLib(a5),a6
  2349.     move.l    ahiac_DriverData(a2),a3
  2350.  
  2351.     push    d0
  2352.     btst    #AHISB_PLAY,d0
  2353.     beq    .dontplay
  2354.  
  2355. **
  2356. *** AHISB_PLAY
  2357. **
  2358.  
  2359.     btst    #PB_DMA,p_Flags(a3)
  2360.     beq    .no_dma
  2361.     bsr    DMA_Stop
  2362.     bra    .playchecked
  2363. .no_dma
  2364.  
  2365.     move.w    #DMAF_AUDIO,DMACON(a4)        ;disable audio DMA
  2366.  
  2367.     and.w    #~INTF_AUD0,p_IRQMask(a3)
  2368.     move.w    #INTF_AUD0,INTENA(a4)
  2369.     move.w    #INTF_AUD0,INTREQ(a4)        ;Clear any waiting interrupts
  2370.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  2371.     lea    p_PlayInt(a3),a1
  2372.     moveq    #INTB_AUD0,d0
  2373.     call    SetIntVector
  2374.  
  2375.     moveq    #0,d0
  2376.     move.w    d0,AUD0VOL(a4)
  2377.     move.w    d0,AUD1VOL(a4)
  2378.     move.w    d0,AUD2VOL(a4)
  2379.     move.w    d0,AUD3VOL(a4)
  2380.  
  2381.     move.l    p_DMAbuffer(a3),d0
  2382.     beq.b    .nodmamem
  2383.     move.l    d0,a1
  2384.     clr.l    p_DMAbuffer(a3)
  2385.     call    FreeVec
  2386. .nodmamem
  2387.     move.l    p_Mixbuffer(a3),d0
  2388.     beq.b    .nomixmem
  2389.     move.l    d0,a1
  2390.     clr.l    p_Mixbuffer(a3)
  2391.     call    FreeVec
  2392. .nomixmem
  2393. .playchecked
  2394.  
  2395. .dontplay
  2396.     pop    d0
  2397.     btst    #AHISB_RECORD,d0
  2398.     beq    .dontrecord
  2399.  
  2400. **
  2401. *** AHISB_RECORD
  2402. **
  2403.     btst    #PB_14BIT,p_Flags(a3)        ;Sanity check...
  2404.     bne    .dontrecord
  2405.  
  2406.     and.w    #~INTF_AUD3,p_IRQMask(a3)
  2407.     move.w    #INTF_AUD3,INTENA(a4)
  2408.     move.w    #INTF_AUD3,INTREQ(a4)        ;Clear any waiting interrupts
  2409.  
  2410.     move.l    #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
  2411.     lea    p_RecInt(a3),a1
  2412.     moveq    #INTB_AUD3,d0
  2413.     call    SetIntVector
  2414.  
  2415.     move.w    #0,AUD2VOL(a4)
  2416.     move.w    #0,AUD3VOL(a4)
  2417.  
  2418.     move.l    p_RecBuffer1(a3),d0
  2419.     beq.b    .norecmem1
  2420.     move.l    d0,a1
  2421.     clr.l    p_RecBuffer1(a3)
  2422.     call    FreeVec
  2423. .norecmem1
  2424.     move.l    p_RecBuffer2(a3),d0
  2425.     beq.b    .norecmem2
  2426.     move.l    d0,a1
  2427.     clr.l    p_RecBuffer2(a3)
  2428.     call    FreeVec
  2429. .norecmem2
  2430. .dontrecord
  2431. .exit
  2432.     moveq    #0,d0
  2433.     popm    std
  2434.     rts
  2435.  
  2436.  
  2437. ****** [driver].audio/AHIsub_GetAttr ****************************************
  2438. *
  2439. *   NAME
  2440. *       AHIsub_GetAttr -- Returns information about audio modes or driver
  2441. *
  2442. *   SYNOPSIS
  2443. *       AHIsub_GetAttr( attribute, argument, default, taglist, audioctrl );
  2444. *       D0              D0         D1        D2       A1       A2
  2445. *
  2446. *       LONG AHIsub_GetAttr( ULONG, LONG, LONG, struct TagItem *,
  2447. *                            struct AHIAudioCtrlDrv * );
  2448. *
  2449. *   IMPLEMENTATION
  2450. *       Return the attribute based on a tag list and an AHIAudioCtrlDrv
  2451. *       structure, which are the same that will be passed to
  2452. *       AHIsub_AllocAudio() by 'ahi.device'. If the attribute is
  2453. *       unknown to you, return the default.
  2454. *
  2455. *   INPUTS
  2456. *       attribute - Is really a Tag and can be one of the following:
  2457. *
  2458. *           AHIDB_Bits - Return how many output bits the tag list will
  2459. *               result in.
  2460. *
  2461. *           AHIDB_MaxChannels - Return the maximum number of channels.
  2462. *
  2463. *           AHIDB_Frequencies - Return how many mixing/sampling frequencies
  2464. *               you support
  2465. *
  2466. *           AHIDB_Frequency - Return the argument:th frequency
  2467. *               Example: You support 3 frequencies; 32, 44.1 and 48 kHz.
  2468. *                   If argument is 1, return 44100.
  2469. *
  2470. *           AHIDB_Index - Return the index which gives the frequency closest
  2471. *               to argument.
  2472. *               Example: You support 3 frequencies; 32, 44.1 and 48 kHz.
  2473. *                   If argument is 40000, return 1 (=> 44100).
  2474. *
  2475. *           AHIDB_Author - Return pointer to name of driver author:
  2476. *               "Martin 'Leviticus' Blom"
  2477. *
  2478. *           AHIDB_Copyright - Return pointer to copyright notice, including
  2479. *               the '©' character: "© 1996 Martin Blom" or "Public Domain"
  2480. *
  2481. *           AHIDB_Version - Return pointer version string, normal Amiga
  2482. *               format: "paula 1.5 (18.2.96)\r\n"
  2483. *
  2484. *           AHIDB_Annotation - Return pointer to an annotation string, which
  2485. *               can be several lines.
  2486. *
  2487. *           AHIDB_Record - Are you a sampler, too? Return TRUE or FALSE.
  2488. *
  2489. *           AHIDB_FullDuplex - Return TRUE or FALSE.
  2490. *
  2491. *           AHIDB_Realtime - Return TRUE or FALSE.
  2492. *
  2493. *           AHIDB_MaxPlaySamples - Normally, return the default. See
  2494. *               AHIsub_AllocAudio(), section 2.
  2495. *
  2496. *           AHIDB_MaxRecordSamples - Return the size of the buffer you fill
  2497. *               when recording.
  2498. *
  2499. *           The following are associated with AHIsub_HardwareControl() and are
  2500. *           new for V2.
  2501. *
  2502. *           AHIDB_MinMonitorVolume
  2503. *           AHIDB_MaxMonitorVolume - Return the lower/upper limit for
  2504. *               AHIC_MonitorVolume. If unsupported but always 1.0, return
  2505. *               1.0 for both.
  2506. *
  2507. *           AHIDB_MinInputGain
  2508. *           AHIDB_MaxInputGain - Return the lower/upper limit for
  2509. *               AHIC_InputGain. If unsupported but always 1.0, return 1.0 for
  2510. *               both.
  2511. *
  2512. *           AHIDB_MinOutputVolume
  2513. *           AHIDB_MaxOutputVolume - Return the lower/upper limit for
  2514. *               AHIC_OutputVolume.
  2515. *
  2516. *           AHIDB_Inputs - Return how many inputs you have.
  2517. *           AHIDB_Input - Return a short string describing the argument:th
  2518. *               input. Number 0 should be the default one. Example strings
  2519. *               can be "Line 1", "Mic", "Optical" or whatever.
  2520. *
  2521. *           AHIDB_Outputs - Return how many outputs you have.
  2522. *           AHIDB_Output - Return a short string describing the argument:th
  2523. *               output. Number 0 should be the default one. Example strings
  2524. *               can be "Line 1", "Headphone", "Optical" or whatever.
  2525. *
  2526. *       argument - extra info for some attributes.
  2527. *       default - What you should return for unknown attributes.
  2528. *       taglist - Pointer to a tag list that eventually will be fed to
  2529. *           AHIsub_AllocAudio(), or NULL.
  2530. *       audioctrl - Pointer to an AHIAudioCtrlDrv structure that eventually
  2531. *           will be fed to AHIsub_AllocAudio(), or NULL.
  2532. *
  2533. *   NOTES
  2534. *
  2535. *   SEE ALSO
  2536. *       AHIsub_AllocAudio(), AHIsub_HardwareControl(),
  2537. *       ahi.device/AHI_GetAudioAttrsA()
  2538. *
  2539. *****************************************************************************
  2540. *
  2541. *
  2542.  
  2543. AHIsub_GetAttr:
  2544.     PRINTF    2,"AHIsub_GetAttr()"
  2545.     pushm    std
  2546.     move.l    a1,a3
  2547.     move.l    a6,a5
  2548.     move.l    pb_UtilLib(a5),a6
  2549.  
  2550.  
  2551.     moveq    #FALSE,d3        ; 14 bit flag
  2552.     moveq    #FALSE,d4        ; DMA flag
  2553.  
  2554.     pushm    d0-d1
  2555.  
  2556.     move.l    a3,a0
  2557.     move.l    a3,d0
  2558.     beq    .notaglist
  2559.  
  2560.     move.l    #AHIDB_Paula14Bit,d0
  2561.     move.l    d3,d1
  2562.     call    GetTagData
  2563.     move.l    d0,d3
  2564.  
  2565.     move.l    a3,a0
  2566.     move.l    #AHIDB_PaulaDMA,d0
  2567.     move.l    d4,d1
  2568.     call    GetTagData
  2569.     move.l    d0,d4
  2570.  
  2571. .notaglist
  2572.  
  2573.     popm    d0-d1
  2574.  
  2575.     and.l    #~(AHI_TagBaseR),d0
  2576.     cmp.l    #AHIDB_Data & ~(AHI_TagBaseR),d0
  2577.     bhi    .default
  2578.     sub.w    #100,d0
  2579.     lsl.w    #1,d0
  2580.     move.w    .jt(pc,d0.w),d0
  2581.     beq    .default
  2582.     jsr    .jt(pc,d0.w)
  2583.  
  2584. .exit
  2585.     popm    std
  2586.     rts
  2587.  
  2588. .default
  2589.     move.l    d2,d0
  2590.     bra    .exit
  2591.  
  2592. .jt
  2593.     dc.w    0                ; AHIDB_AudioID
  2594.     dc.w    0                ; AHIDB_Driver
  2595.     dc.w    0                ; AHIDB_Flags
  2596.     dc.w    ga_Volume-.jt            ; AHIDB_Volume
  2597.     dc.w    ga_Panning-.jt            ; AHIDB_Panning
  2598.     dc.w    ga_Stereo-.jt            ; AHIDB_Stereo
  2599.     dc.w    ga_HiFi-.jt            ; AHIDB_HiFi
  2600.     dc.w    ga_PingPong-.jt            ; AHIDB_PingPong
  2601.     dc.w    0                ; AHIDB_MultTable
  2602.     dc.w    0                ; AHIDB_Name
  2603.     dc.w    ga_Bits-.jt            ; AHIDB_Bits
  2604.     dc.w    ga_MaxChannels-.jt        ; AHIDB_MaxChannels
  2605.     dc.w    0                ; AHIDB_MinMixFreq
  2606.     dc.w    0                ; AHIDB_MaxMixFreq
  2607.     dc.w    ga_Record-.jt            ; AHIDB_Record
  2608.     dc.w    ga_Frequencies-.jt        ; AHIDB_Frequencies
  2609.     dc.w    0                ; AHIDB_FrequencyArg
  2610.     dc.w    ga_Frequency-.jt        ; AHIDB_Frequency
  2611.     dc.w    ga_Author-.jt            ; AHIDB_Author
  2612.     dc.w    ga_Copyright-.jt        ; AHIDB_Copyright
  2613.     dc.w    ga_Version-.jt            ; AHIDB_Version
  2614.     dc.w    ga_Annotation-.jt        ; AHIDB_Annotation
  2615.     dc.w    0                ; AHIDB_BufferLen
  2616.     dc.w    0                ; AHIDB_IndexArg
  2617.     dc.w    ga_Index-.jt            ; AHIDB_Index
  2618.     dc.w    ga_Realtime-.jt            ; AHIDB_Realtime
  2619.     dc.w    0                ; AHIDB_MaxPlaySamples
  2620.     dc.w    ga_MaxRecordSamples-.jt        ; AHIDB_MaxRecordSample
  2621.     dc.w    0                ; 
  2622.     dc.w    ga_FullDuplex-.jt        ; AHIDB_FullDuplex
  2623.     dc.w    ga_MinMonitorVolume-.jt        ; AHIDB_MinMonitorVolum
  2624.     dc.w    ga_MaxMonitorVolume-.jt        ; AHIDB_MaxMonitorVolum
  2625.     dc.w    ga_MinInputGain-.jt        ; AHIDB_MinInputGain
  2626.     dc.w    ga_MaxInputGain-.jt        ; AHIDB_MaxInputGain
  2627.     dc.w    ga_MinOutputVolume-.jt        ; AHIDB_MinOutputVolume
  2628.     dc.w    ga_MaxOutputVolume-.jt        ; AHIDB_MaxOutputVolume
  2629.     dc.w    ga_Inputs-.jt            ; AHIDB_Inputs
  2630.     dc.w    0                ; AHIDB_InputArg
  2631.     dc.w    ga_Input-.jt            ; AHIDB_Input
  2632.     dc.w    ga_Outputs-.jt            ; AHIDB_Outputs
  2633.     dc.w    0                ; AHIDB_OutputArg
  2634.     dc.w    ga_Output-.jt            ; AHIDB_Output
  2635.     dc.w    0                ; AHIDB_Data
  2636.  
  2637.  
  2638. *** The tags AHIDB_Volume, AHIDB_Panning, AHIDB_Stereo and AHIDB_HiFi are
  2639. *** parameters to the mixing routine when mixing, but attributes in DMA mode.
  2640.  
  2641. ga_Volume:
  2642.     move.l    d2,d0
  2643.     tst.l    d4
  2644.     beq    .exit
  2645.     moveq    #TRUE,d0
  2646. .exit
  2647.     rts
  2648.  
  2649. ga_Panning:
  2650.     move.l    d2,d0
  2651.     tst.l    d4
  2652.     beq    .exit
  2653.     moveq    #FALSE,d0
  2654. .exit
  2655.     rts
  2656.  
  2657. ga_Stereo:
  2658.     move.l    d2,d0
  2659.     tst.l    d4
  2660.     beq    .exit
  2661.     moveq    #TRUE,d0
  2662. .exit
  2663.     rts
  2664.  
  2665. ga_HiFi:
  2666.     move.l    d2,d0
  2667.     tst.l    d4
  2668.     beq    .exit
  2669.     moveq    #TRUE,d0
  2670. .exit
  2671.     rts
  2672.  
  2673. ga_PingPong:
  2674.     move.l    d2,d0
  2675.     tst.l    d4
  2676.     beq    .exit
  2677.     moveq    #TRUE,d0
  2678. .exit
  2679.     rts
  2680.  
  2681. ga_Bits:
  2682.     moveq    #14,d0
  2683.     tst.l    d3
  2684.     bne    .exit
  2685.     moveq    #8,d0
  2686. .exit
  2687.     rts
  2688.  
  2689. ga_MaxChannels:
  2690.     moveq    #4,d0
  2691.     tst.l    d4
  2692.     bne    .exit
  2693.     move.l    d2,d0
  2694. .exit
  2695.     rts
  2696.  
  2697. ga_Record:
  2698.     moveq    #FALSE,d0
  2699.     tst.l    d3
  2700.     bne    .exit
  2701.     tst.l    d4
  2702.     bne    .exit
  2703.     moveq    #TRUE,d0
  2704. .exit
  2705.     rts
  2706.  
  2707. ga_Frequencies:
  2708.     moveq    #1,d0
  2709.     tst.l    d4
  2710.     bne    .exit
  2711.     bsr    checkvideo
  2712.     tst.l    d0
  2713.     beq    .1
  2714.     moveq    #FREQUENCIES,d0
  2715. .exit
  2716.     rts
  2717. .1
  2718.     moveq    #FREQUENCIES_OCS,d0
  2719.     rts
  2720.  
  2721. ga_Frequency:
  2722.     tst.l    d4
  2723.     beq    .nodma
  2724.     move.l    #PALFREQ,d2            ;PAL
  2725.     move.l    pb_GfxLib(a5),a0
  2726.     move.w    gb_DisplayFlags(a0),d0
  2727.     btst    #REALLY_PALn,d0
  2728.     bne.b    .1
  2729.     move.l    #NTSCFREQ,d2            ;NTSC
  2730. .1
  2731.     move.l    d2,d0
  2732.     rts
  2733. .nodma
  2734.     lsl.w    #2,d1
  2735.     lea    freqlist(pc),a0
  2736.     move.l    (a0,d1.w),d0
  2737.     rts
  2738.  
  2739. ga_Author:
  2740.     lea    .author(pc),a0
  2741.     move.l    a0,d0
  2742.     rts
  2743. .author        dc.b    "Martin 'Leviticus' Blom",0
  2744.     even
  2745.  
  2746. ga_Copyright:
  2747.     lea    .copyright(pc),a0
  2748.     move.l    a0,d0
  2749.     rts
  2750. .copyright    dc.b    "Public Domain",0
  2751.     even
  2752.  
  2753. ga_Version:
  2754.     lea    IDString(pc),a0
  2755.     move.l    a0,d0
  2756.     rts
  2757.  
  2758. ga_Annotation:
  2759.     lea    .anno(pc),a0
  2760.     move.l    a0,d0
  2761.     rts
  2762. .anno        dc.b    "14 bit routines by Christian Buchner.",0
  2763.     even
  2764.  
  2765. ga_Index:
  2766.     move.l    d1,d0
  2767.     bsr    findfreq
  2768.     move.l    d1,d0
  2769.     rts
  2770.  
  2771.  
  2772. ga_Realtime:
  2773.     moveq    #TRUE,d0
  2774.     rts
  2775.  
  2776. ga_MaxRecordSamples:
  2777.     move.l    #RECORDSAMPLES,d0
  2778.     rts
  2779.  
  2780. ga_FullDuplex:
  2781.     moveq    #FALSE,d0
  2782.     tst.l    d3
  2783.     bne    .exit
  2784.     tst.l    d4
  2785.     bne    .exit
  2786.     moveq    #TRUE,d0
  2787. .exit
  2788.     rts
  2789.  
  2790.  
  2791. ga_MinMonitorVolume:
  2792.     moveq    #0,d0
  2793.     rts
  2794.  
  2795. ga_MaxMonitorVolume:
  2796.     moveq    #0,d0
  2797.     tst.l    d3
  2798.     bne    .exit
  2799.     tst.l    d4
  2800.     bne    .exit
  2801.     move.l    #$10000,d0
  2802. .exit
  2803.     rts
  2804.  
  2805. ga_MinInputGain:
  2806.     move.l    #$10000,d0
  2807.     rts
  2808.  
  2809. ga_MaxInputGain:
  2810.     move.l    #$10000,d0
  2811.     rts
  2812.  
  2813. ga_MinOutputVolume:
  2814.     move.l    #$10000,d0
  2815.     tst.l    d3
  2816.     bne    .exit
  2817.     tst.l    d4
  2818.     bne    .exit
  2819.     moveq    #0,d0
  2820. .exit
  2821.     rts
  2822.  
  2823. ga_MaxOutputVolume:
  2824.     move.l    #$10000,d0
  2825.     rts
  2826.  
  2827.  
  2828. ga_Inputs:
  2829.     moveq    #0,d0
  2830.     tst.l    d3
  2831.     bne    .exit
  2832.     tst.l    d4
  2833.     bne    .exit
  2834.     moveq    #3,d0
  2835. .exit
  2836.     rts
  2837.  
  2838. ga_Input:
  2839.     lsl.l    #2,d1
  2840.     move.l    .inputs(pc,d1.w),d0
  2841.     rts
  2842. .inputs        dc.l    .input0
  2843.         dc.l    .input1
  2844.         dc.l    .input2
  2845.  
  2846. .input0        dc.b    "Parallel port sampler",0
  2847. .input1        dc.b    "Aura sampler",0
  2848. .input2        dc.b    "Clarity sampler",0
  2849.     even
  2850.  
  2851. ga_Outputs:
  2852.     moveq    #1,d0
  2853.     rts
  2854.  
  2855. ga_Output:
  2856.     lea    .output(pc),a0
  2857.     move.l    a0,d0
  2858.     rts
  2859. .output        dc.b    "Line",0
  2860.     even
  2861.  
  2862.  
  2863. ****** [driver].audio/AHIsub_HardwareControl ********************************
  2864. *
  2865. *   NAME
  2866. *       AHIsub_HardwareControl -- Modify sound card settings
  2867. *
  2868. *   SYNOPSIS
  2869. *       AHIsub_HardwareControl( attribute,  argument, audioctrl );
  2870. *       D0                      D0          D1        A2
  2871. *
  2872. *       LONG AHIsub_HardwareControl( ULONG, LONG, struct AHIAudioCtrlDrv * );
  2873. *
  2874. *   IMPLEMENTATION
  2875. *       Set or return the state of a particular hardware component. AHI uses
  2876. *       AHIsub_GetAttr() to supply the user with limits and what tags are
  2877. *       available.
  2878. *
  2879. *   INPUTS
  2880. *       attribute - Is really a Tag and can be one of the following:
  2881. *
  2882. *           AHIC_MonitorVolume - Set the input monitor volume to argument.
  2883. *           AHIC_MonitorVolume_Query - Return the current input monitor
  2884. *               volume (argument is ignored).
  2885. *
  2886. *           AHIC_InputGain - Set the input gain to argument. (V2)
  2887. *           AHIC_InputGain_Query (V2)
  2888. *
  2889. *           AHIC_OutputVolume - Set the output volume to argument. (V2)
  2890. *           AHIC_OutputVolume_Query (V2)
  2891. *
  2892. *           AHIC_Input - Use the argument:th input source (default is 0). (V2)
  2893. *           AHIC_Input_Query (V2)
  2894. *
  2895. *           AHIC_Output - Use the argument:th output destination (default
  2896. *               is 0). (V2)
  2897. *           AHIC_Output_Query (V2)
  2898. *
  2899. *       argument - What value attribute should be set to.
  2900. *       audioctrl - Pointer to an AHIAudioCtrlDrv structure.
  2901. *
  2902. *   RESULT
  2903. *       Return the state of selected attribute. If you were asked to set
  2904. *       something, return TRUE. If attribute is unknown to you or unsupported,
  2905. *       return FALSE.
  2906. *
  2907. *   NOTES
  2908. *       This call must be safe from interrupts.
  2909. *
  2910. *   SEE ALSO
  2911. *       ahi.device/AHI_ControlAudioA(), AHIsub_GetAttr()
  2912. *
  2913. *****************************************************************************
  2914. *
  2915. *
  2916.  
  2917. AHIsub_HardwareControl:
  2918.     PRINTF    2,"AHIsub_HardwareControl()"
  2919.     cmp.l    #AHIC_MonitorVolume,d0
  2920.     bne.b    .dontsetmonvol
  2921.     move.l    ahiac_DriverData(a2),a1
  2922.     lsr.l    #8,d1
  2923.     lsr.l    #2,d1
  2924.     move.w    d1,p_MonitorVolume(a1)
  2925.     bra.b    .exit
  2926. .dontsetmonvol
  2927.     cmp.l    #AHIC_MonitorVolume_Query,d0
  2928.     bne.b    .dontgetmonvol
  2929.     move.l    ahiac_DriverData(a2),a1
  2930.     moveq    #0,d0
  2931.     move.w    p_MonitorVolume(a1),d0
  2932.     lsl.l    #8,d0
  2933.     lsl.l    #2,d0
  2934.     bra.b    .quit
  2935. .dontgetmonvol
  2936.     cmp.l    #AHIC_OutputVolume,d0
  2937.     bne.b    .dontsetoutvol
  2938.     move.l    ahiac_DriverData(a2),a1
  2939.     lsr.l    #8,d1
  2940.     lsr.l    #2,d1
  2941.     move.w    d1,p_OutputVolume(a1)
  2942.     bra.b    .exit
  2943. .dontsetoutvol
  2944.     cmp.l    #AHIC_OutputVolume_Query,d0
  2945.     bne.b    .dontgetoutvol
  2946.     move.l    ahiac_DriverData(a2),a1
  2947.     moveq    #0,d0
  2948.     move.w    p_OutputVolume(a1),d0
  2949.     lsl.l    #8,d0
  2950.     lsl.l    #2,d0
  2951.     bra.b    .quit
  2952. .dontgetoutvol
  2953.     cmp.l    #AHIC_Input,d0
  2954.     bne.b    .dontsetinput
  2955.     move.l    ahiac_DriverData(a2),a1
  2956.     move.w    d1,p_Input(a1)
  2957.     bra.b    .exit
  2958. .dontsetinput
  2959.     cmp.l    #AHIC_Input_Query,d0
  2960.     bne.b    .dontgetinput
  2961.     move.l    ahiac_DriverData(a2),a1
  2962.     moveq    #0,d0
  2963.     move.w    p_Input(a1),d0
  2964.     bra.b    .quit
  2965. .dontgetinput
  2966.     moveq    #FALSE,d0
  2967. .quit
  2968.     rts
  2969. .exit
  2970.     moveq    #TRUE,d0
  2971.     rts
  2972.  
  2973.  
  2974.  
  2975.  
  2976.  
  2977.  
  2978.  
  2979. *******************************************************************************
  2980. ***** Interrupt routines ******************************************************
  2981. *******************************************************************************
  2982.  
  2983. Interrupt_Dummy:
  2984.     move.w    #INTF_AUDIO,INTREQ(a0)
  2985. SoftInt_Dummy:
  2986.     rts
  2987.  
  2988. ;in:
  2989. * d0    scratch
  2990. * d1    INTENAR & INTREQR
  2991. * a0    custom
  2992. * a1    &(paula->p_RecIntData)
  2993. * a5    &RecordInterrupt
  2994. * a6    ExecBase
  2995. RecordInterrupt:
  2996.  
  2997. * This function will be executed up to 28000 times per second - that's once per
  2998. * rasterline! It has to be as fast as possible.
  2999.  
  3000.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  3001.     moveq    #0,d0
  3002.     move.b    _ciaa+ciaprb,d0            ;read parallel port
  3003.  IFGE    __CPU-68020
  3004.     move.l    convtable(pc,d0.w*4),d0        ;1 unsigned byte -> 2 signed words
  3005.  ELSE
  3006.     add.w    d0,d0
  3007.     add.w    d0,d0
  3008.     move.l    convtable(pc,d0.w),d0
  3009.  ENDC
  3010.     move.w    d0,AUD2DAT(a0)            ;left
  3011.     move.w    d0,AUD3DAT(a0)            ;right
  3012.  
  3013.     move.l    (a1),a5                ;p_RecFillPtr
  3014.     move.l    d0,(a5)+            ;store sample in buffer
  3015.     move.l    a5,(a1)+            ;update pointer
  3016.     subq.w    #1,(a1)                ;p_ReqFillCount
  3017.     beq    ri_Filled            ;branch if buffer filled
  3018.     rts
  3019.  
  3020. convtable
  3021. CNT    SET    0
  3022.     REPT    256
  3023.     dc.b    CNT-128,CNT-128,CNT-128,CNT-128
  3024. CNT    SET    CNT+1
  3025.     ENDR
  3026.  
  3027. ;in:
  3028. * d0    scratch
  3029. * d1    INTENAR & INTREQR
  3030. * a0    custom
  3031. * a1    &(paula->p_RecIntData)
  3032. * a5    &RecordInterrupt
  3033. * a6    ExecBase
  3034. RecordInterruptClarity:
  3035.  
  3036. * This function will be executed up to 28000 times per second - that's once per
  3037. * rasterline! It has to be as fast as possible.
  3038.  
  3039.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  3040.  
  3041.     lea    _ciab+ciatahi,a5
  3042.  
  3043.     move.b    _ciaa+ciaprb,d0            ;left lsb
  3044.     ror.l    #8,d0                ;d0: L0xxxxxx
  3045.     tst.b    (a5)                ;3x700 kHz wait states
  3046.     tst.b    (a5)
  3047.     tst.b    (a5)
  3048.  
  3049.     move.b    _ciaa+ciaprb,d0            ;left msb
  3050.     ror.l    #8,d0                ;d0: L1L0xxxx
  3051.     tst.b    (a5)                ;3x700 kHz wait states
  3052.     tst.b    (a5)
  3053.     tst.b    (a5)
  3054.  
  3055.     move.b    _ciaa+ciaprb,d0            ;right lsb
  3056.     lsl.w    #8,d0                ;d0: L1L0R0xx
  3057.     tst.b    (a5)                ;3x700 kHz wait states
  3058.     tst.b    (a5)
  3059.     tst.b    (a5)
  3060.  
  3061.     move.b    _ciaa+ciaprb,d0            ;right msb
  3062.     ror.w    #8,d0                ;d0: L1L0R1R0
  3063.  
  3064.     move.l    (a1),a5                ;p_RecFillPtr
  3065.     move.l    d0,(a5)+            ;store sample in buffer
  3066.     move.l    a5,(a1)+            ;update pointer
  3067.  
  3068.     move.w    d0,d1
  3069.     lsr.w    #8,d0
  3070.     move.b    d0,d1
  3071.  
  3072.     move.w    d1,AUD2DAT(a0)            ;right
  3073.     move.w    d1,AUD3DAT(a0)            ;left
  3074.  
  3075.     subq.w    #1,(a1)                ;p_ReqFillCount
  3076.     beq    ri_Filled            ;branch if buffer filled
  3077.     rts
  3078.  
  3079. ;in:
  3080. * d0    scratch
  3081. * d1    INTENAR & INTREQR
  3082. * a0    custom
  3083. * a1    &(paula->p_RecIntDataAura)
  3084. * a5    &RecordInterrupt
  3085. * a6    ExecBase
  3086. RecordInterruptAura:
  3087.  
  3088. * This function will be executed up to 28000 times per second - that's once per
  3089. * rasterline! It has to be as fast as possible.
  3090.  
  3091.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  3092.     move.l    (a1)+,a5
  3093.     move.l    (a5),d0                ;read aura sampler
  3094.     eor.l    #$80008000,d0
  3095.     move.l    (a1),a5                ;p_RecFillPtr
  3096.     move.l    d0,(a5)+            ;store sample in buffer
  3097.     move.l    a5,(a1)+            ;update pointer
  3098.  
  3099.     move.w    d0,d1
  3100.     lsr.w    #8,d0
  3101.     move.b    d0,d1
  3102.  
  3103.     move.w    d1,AUD2DAT(a0)            ;left
  3104.     move.w    d1,AUD3DAT(a0)            ;right
  3105.  
  3106.     subq.w    #1,(a1)                ;p_ReqFillCount
  3107.     beq    ri_Filled            ;branch if buffer filled
  3108.     rts
  3109.  
  3110. *******************************************************************************
  3111.  
  3112. ri_Filled:
  3113.  
  3114. * This part is only executed every RECORDSAMPLES:th time... No need to hurry.
  3115.  
  3116.     move.l    8(a1),d0            ;p_RecBuffer2->
  3117.     move.l    4(a1),8(a1)            ;p_RecBuffer1->p_RecBuffer2
  3118.     move.l    d0,4(a1)            ;            ->p_RecBuffer1
  3119.     move.l    d0,-4(a1)            ;p_RecFillPtr
  3120.     move.w    #RECORDSAMPLES,(a1)        ;p_ReqFillCount
  3121.     move.l    12(a1),a1            ;p_RecSoftIntPtr
  3122.     jmp    _LVOCause(a6)
  3123.  
  3124.  
  3125. ;in:
  3126. * d0    scratch
  3127. * d1    scratch
  3128. * a0    scratch
  3129. * a1    struct paula *
  3130. * a5    scratch
  3131. RecordSoftInt:
  3132.  
  3133. * This function is not executed many times per second and is therefore not
  3134. * fully optimized... ;)
  3135.     push    a2
  3136.     move.w    p_MonitorVolume(a1),d0
  3137.     move.w    d0,custom+AUD2VOL
  3138.     move.w    d0,custom+AUD3VOL
  3139.     move.l    p_RecBuffer2(a1),p_rmBuffer(a1)
  3140.     move.l    p_AudioCtrl(a1),a2
  3141.     lea    p_RecordMessage(a1),a1
  3142.     move.l    ahiac_SamplerFunc(a2),a0
  3143.     move.l    h_Entry(a0),a5
  3144.     jsr    (a5)
  3145.     pop    a2
  3146.     rts
  3147.  
  3148. *******************************************************************************
  3149. *******************************************************************************
  3150.  
  3151. ;in:
  3152. * d0    scratch
  3153. * d1    INTENAR & INTREQR
  3154. * a0    custom
  3155. * a1    struct paula *
  3156. * a5    &AudioInterrupt
  3157. * a6    ExecBase
  3158.  
  3159. AudioInterrupt2:                ;Two hardware channels used
  3160. ;    move.l    p_AudLenPer(a1),d0
  3161. ;    move.l    d0,AUD0LEN(a0)
  3162. ;    move.l    d0,AUD1LEN(a0)
  3163.     move.w    p_AudPer(a1),d0
  3164.     move.w    d0,AUD0PER(a0)
  3165.     move.w    d0,AUD1PER(a0)
  3166.     move.w    p_OutputVolume(a1),AUD0VOL(a0)
  3167.     move.w    p_OutputVolume(a1),AUD1VOL(a0)
  3168.  
  3169.     move.l    p_DoubleBufferOffset(a1),d0
  3170.     eor.w    #4*4,d0
  3171.     move.l    d0,p_DoubleBufferOffset(a1)
  3172.  
  3173.     lea    p_AudPtrs(a1,d0.l),a5
  3174.     tst.w    p_SwapChannels(a1)
  3175.     bne    .swap
  3176.     move.l    (a5)+,AUD0LC(a0)
  3177.     move.l    (a5)+,AUD1LC(a0)
  3178.     bra    .1
  3179. .swap
  3180.     move.l    (a5)+,AUD1LC(a0)
  3181.     move.l    (a5)+,AUD0LC(a0)
  3182. .1
  3183.     lea    p_PlaySoftInt(a1),a1
  3184.     move.w    #INTF_AUD0,INTREQ(a0)        ;Clear the interrupt 
  3185.     jmp    _LVOCause(a6)            ;start PlaySoftInt
  3186.  
  3187.  
  3188. AudioInterrupt4:                ;Four hardware channels used
  3189. ;    move.l    p_AudLenPer(a1),d0
  3190. ;    move.l    d0,AUD0LEN(a0)
  3191. ;    move.l    d0,AUD1LEN(a0)
  3192. ;    move.l    d0,AUD2LEN(a0)
  3193. ;    move.l    d0,AUD3LEN(a0)
  3194.     move.w    p_AudPer(a1),d0
  3195.     move.w    d0,AUD0PER(a0)
  3196.     move.w    d0,AUD1PER(a0)
  3197.     move.w    d0,AUD2PER(a0)
  3198.     move.w    d0,AUD3PER(a0)
  3199.     move.w    #64,AUD0VOL(a0)
  3200.     move.w    #64,AUD1VOL(a0)
  3201.     move.w    #1,AUD2VOL(a0)
  3202.     move.w    #1,AUD3VOL(a0)
  3203.  
  3204.     move.l    p_DoubleBufferOffset(a1),d0
  3205.     eor.w    #4*4,d0
  3206.     move.l    d0,p_DoubleBufferOffset(a1)
  3207.  
  3208.     lea    p_AudPtrs(a1,d0.l),a5
  3209.     tst.w    p_SwapChannels(a1)
  3210.     bne    .swap
  3211.     move.l    (a5)+,AUD0LC(a0)
  3212.     move.l    (a5)+,AUD1LC(a0)
  3213.     move.l    (a5)+,AUD2LC(a0)
  3214.     move.l    (a5)+,AUD3LC(a0)
  3215.     bra    .1
  3216. .swap
  3217.     move.l    (a5)+,AUD1LC(a0)
  3218.     move.l    (a5)+,AUD0LC(a0)
  3219.     move.l    (a5)+,AUD3LC(a0)
  3220.     move.l    (a5)+,AUD2LC(a0)
  3221. .1
  3222.     lea    p_PlaySoftInt(a1),a1
  3223.     move.w    #INTF_AUD0,INTREQ(a0)        ;Clear the interrupt 
  3224.     jmp    _LVOCause(a6)            ;start PlaySoftInt
  3225.  
  3226.  
  3227. *******************************************************************************
  3228.  
  3229. ;in:
  3230. * d0    scratch
  3231. * d1    scratch
  3232. * a0    scratch
  3233. * a1    struct paula *
  3234. * a5    scratch
  3235.  
  3236. CONVERT_PRE    MACRO
  3237.     pushm    std
  3238.     move.l    a1,a6
  3239.     move.l    p_AudioCtrl(a6),a2
  3240.     move.l    ahiac_PreTimer(a2),a0
  3241.     jsr    (a0)
  3242.     move.l    d0,d7
  3243.  
  3244.     move.l    p_DoubleBufferOffset(a6),d0
  3245.     lea    p_AudPtrs(a6,d0.l),a0
  3246.     movem.l    (a0)+,d2/d3/d4/d5        ;get all 4 buffer pointers
  3247.  
  3248.     moveq    #0,d6
  3249. .repeat
  3250.     movem.l    p_PlayerHookRegs(a6),a0/a1/a3
  3251.     jsr    (a3)                ;call Player Hook
  3252.     tst.l    d7
  3253.     bne    .skip
  3254.     movem.l    p_MixHookRegs(a6),a0/a1/a3
  3255.     jsr    (a3)                ;call Mixer Hook
  3256.     move.l    p_LoopTimes(a6),d0
  3257.     ENDM
  3258.  
  3259. ;
  3260. ; Conversion code here!
  3261. ;
  3262. ; d0    counter
  3263. ; d1    scratch
  3264. ; d2-d5    buffer pointers
  3265. ; d6    (sample counter/4)
  3266. ; d7    (pretimer flag)
  3267. ; a0    scratch
  3268. ; a1    source buffer
  3269. ; a2    AudioCtrl
  3270. ; a3-a5    scratch
  3271. ; a6    struct paula *
  3272. ;
  3273. ; Conversion code here!
  3274. ;
  3275.  
  3276. CONVERT_POST    MACRO
  3277. .skip
  3278.     add.l    ahiac_BuffSamples(a2),d6
  3279.     cmp.l    p_MinBufferLength(a6),d6
  3280.     blo    .repeat
  3281.     move.l    ahiac_PostTimer(a2),a0
  3282.     jsr    (a0)
  3283.     move.l    d6,d0
  3284.     lea    custom,a0
  3285.     popm    std
  3286.     ENDM
  3287.  
  3288. ; Exit code here
  3289. ; d0    Samples in buffer
  3290. ; a0    custom
  3291.  
  3292. *******************************************************************************
  3293.  
  3294. SoftInt_8bitM:
  3295.  
  3296.     CONVERT_PRE
  3297.  
  3298.     move.l    d2,a0                ;get buffer ptr
  3299. .loop
  3300.     move.b    (a1),d1
  3301.     lsl.l    #8,d1
  3302.     move.b    2(a1),d1
  3303.     lsl.l    #8,d1
  3304.     move.b    4(a1),d1
  3305.     lsl.l    #8,d1
  3306.     move.b    6(a1),d1
  3307.     move.l    d1,(a0)+
  3308.     addq.w    #8,a1
  3309.     dbf    d0,.loop
  3310.     move.l    a0,d2                ;save buffer ptr
  3311.  
  3312.     CONVERT_POST
  3313.  
  3314.     lsr.l    #1,d0
  3315.     move.w    d0,AUD0LEN(a0)
  3316.     move.w    d0,AUD1LEN(a0)
  3317.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3318.     rts
  3319.  
  3320. *******************************************************************************
  3321.  
  3322. SoftInt_8bitMH:
  3323.     CONVERT_PRE
  3324.  
  3325.     move.l    d2,a0                ;get buffer ptr
  3326. .loop
  3327.     move.b    (a1),d1
  3328.     lsl.l    #8,d1
  3329.     move.b    4(a1),d1
  3330.     lsl.l    #8,d1
  3331.     move.b    8(a1),d1
  3332.     lsl.l    #8,d1
  3333.     move.b    12(a1),d1
  3334.     move.l    d1,(a0)+
  3335.     add.w    #16,a1
  3336.     dbf    d0,.loop
  3337.     move.l    a0,d2                ;save buffer ptr
  3338.  
  3339.     CONVERT_POST
  3340.  
  3341.     lsr.l    #1,d0
  3342.     move.w    d0,AUD0LEN(a0)
  3343.     move.w    d0,AUD1LEN(a0)
  3344.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3345.     rts
  3346.  
  3347. *******************************************************************************
  3348.  
  3349. SoftInt_8bitS:
  3350.     CONVERT_PRE
  3351.  
  3352.     move.l    d2,a0                ;get buffer ptr
  3353.     move.l    d3,a3                ;get buffer ptr
  3354. .loop
  3355.  
  3356. ; Left
  3357.     move.b    (a1),d1
  3358.     lsl.l    #8,d1
  3359.     move.b    4(a1),d1
  3360.     lsl.l    #8,d1
  3361.     move.b    8(a1),d1
  3362.     lsl.l    #8,d1
  3363.     move.b    12(a1),d1
  3364.     move.l    d1,(a3)+
  3365.  
  3366. ; Right
  3367.     move.b    2(a1),d1
  3368.     lsl.l    #8,d1
  3369.     move.b    6(a1),d1
  3370.     lsl.l    #8,d1
  3371.     move.b    10(a1),d1
  3372.     lsl.l    #8,d1
  3373.     move.b    14(a1),d1
  3374.     move.l    d1,(a0)+
  3375.  
  3376.     add.w    #16,a1
  3377.     dbf    d0,.loop
  3378.     move.l    a0,d2                ;save buffer ptr
  3379.     move.l    a3,d3                ;save buffer ptr
  3380.  
  3381.     CONVERT_POST
  3382.  
  3383.     lsr.l    #1,d0
  3384.     move.w    d0,AUD0LEN(a0)
  3385.     move.w    d0,AUD1LEN(a0)
  3386.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3387.     rts
  3388.  
  3389. *******************************************************************************
  3390.  
  3391. SoftInt_8bitSH:
  3392.     CONVERT_PRE
  3393.  
  3394.     move.l    d2,a0                ;get buffer ptr
  3395.     move.l    d3,a3                ;get buffer ptr
  3396. .loop
  3397.  
  3398. ; Left
  3399.     move.b    (a1),d1
  3400.     lsl.l    #8,d1
  3401.     move.b    8(a1),d1
  3402.     lsl.l    #8,d1
  3403.     move.b    16(a1),d1
  3404.     lsl.l    #8,d1
  3405.     move.b    24(a1),d1
  3406.     move.l    d1,(a3)+
  3407.  
  3408. ; Right
  3409.     move.b    4(a1),d1
  3410.     lsl.l    #8,d1
  3411.     move.b    12(a1),d1
  3412.     lsl.l    #8,d1
  3413.     move.b    20(a1),d1
  3414.     lsl.l    #8,d1
  3415.     move.b    28(a1),d1
  3416.     move.l    d1,(a0)+
  3417.  
  3418.     add.w    #32,a1
  3419.     dbf    d0,.loop
  3420.     move.l    a0,d2                ;save buffer ptr
  3421.     move.l    a3,d3                ;save buffer ptr
  3422.  
  3423.     CONVERT_POST
  3424.  
  3425.     lsr.l    #1,d0
  3426.     move.w    d0,AUD0LEN(a0)
  3427.     move.w    d0,AUD1LEN(a0)
  3428.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3429.     rts
  3430.  
  3431. *******************************************************************************
  3432.  
  3433. SoftInt_14bitM:
  3434.     CONVERT_PRE
  3435.  
  3436.     move.l    d2,a0                ;get buffer ptr
  3437.     move.l    d5,a5                ;get buffer ptr
  3438. .loop
  3439.  
  3440. ; High
  3441.     move.b    (a1),d1
  3442.     lsl.l    #8,d1
  3443.     move.b    2(a1),d1
  3444.     lsl.l    #8,d1
  3445.     move.b    4(a1),d1
  3446.     lsl.l    #8,d1
  3447.     move.b    6(a1),d1
  3448.     move.l    d1,(a0)+
  3449.  
  3450. ; Low
  3451.     move.b    1(a1),d1
  3452.     lsr.b    #2,d1
  3453.     lsl.l    #8,d1
  3454.     move.b    3(a1),d1
  3455.     lsr.b    #2,d1
  3456.     lsl.l    #8,d1
  3457.     move.b    5(a1),d1
  3458.     lsr.b    #2,d1
  3459.     lsl.l    #8,d1
  3460.     move.b    7(a1),d1
  3461.     lsr.b    #2,d1
  3462.     move.l    d1,(a5)+
  3463.  
  3464.     addq.w    #8,a1
  3465.     dbf    d0,.loop
  3466.     move.l    a0,d2                ;save buffer ptr
  3467.     move.l    a5,d5                ;save buffer ptr
  3468.  
  3469.     CONVERT_POST
  3470.  
  3471.     lsr.l    #1,d0
  3472.     move.w    d0,AUD0LEN(a0)
  3473.     move.w    d0,AUD1LEN(a0)
  3474.     move.w    d0,AUD2LEN(a0)
  3475.     move.w    d0,AUD3LEN(a0)
  3476.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3477.     rts
  3478.  
  3479. *******************************************************************************
  3480.  
  3481.  
  3482. SoftInt_14bitMH:
  3483.     CONVERT_PRE
  3484.  
  3485.     move.l    d2,a0                ;get buffer ptr
  3486.     move.l    d5,a5                ;get buffer ptr
  3487. .loop
  3488.  
  3489. ; High
  3490.     move.b    (a1),d1
  3491.     lsl.l    #8,d1
  3492.     move.b    4(a1),d1
  3493.     lsl.l    #8,d1
  3494.     move.b    8(a1),d1
  3495.     lsl.l    #8,d1
  3496.     move.b    12(a1),d1
  3497.     move.l    d1,(a0)+
  3498.  
  3499. ; Low
  3500.     move.b    1(a1),d1
  3501.     lsr.b    #2,d1
  3502.     lsl.l    #8,d1
  3503.     move.b    5(a1),d1
  3504.     lsr.b    #2,d1
  3505.     lsl.l    #8,d1
  3506.     move.b    9(a1),d1
  3507.     lsr.b    #2,d1
  3508.     lsl.l    #8,d1
  3509.     move.b    13(a1),d1
  3510.     lsr.b    #2,d1
  3511.     move.l    d1,(a5)+
  3512.  
  3513.     add.w    #16,a1
  3514.     dbf    d0,.loop
  3515.     move.l    a0,d2                ;save buffer ptr
  3516.     move.l    a5,d5                ;save buffer ptr
  3517.  
  3518.     CONVERT_POST
  3519.  
  3520.     lsr.l    #1,d0
  3521.     move.w    d0,AUD0LEN(a0)
  3522.     move.w    d0,AUD1LEN(a0)
  3523.     move.w    d0,AUD2LEN(a0)
  3524.     move.w    d0,AUD3LEN(a0)
  3525.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3526.     rts
  3527.  
  3528. *******************************************************************************
  3529.  
  3530. SoftInt_14CbitM:
  3531.     CONVERT_PRE
  3532.  
  3533.     move.l    d2,a0                ;get buffer ptr
  3534.     move.l    d5,a5                ;get buffer ptr
  3535.     move.l    p_CalibrationTable(a6),a3
  3536.     moveq    #0,d3
  3537. .loop
  3538.  
  3539.  IFGE    __CPU-68020
  3540.     move.w    (a1)+,d3
  3541.     move.w    (a3,d3.l*2),d3
  3542.  ELSE
  3543.     moveq    #0,d3
  3544.     move.w    (a1)+,d3
  3545.      add.w    d3,d3
  3546.      move.w    (a3,d3.l),d3
  3547.  ENDC
  3548.     move.b    d3,d1
  3549.     lsl.l    #8,d1                ;xxxxAAxx
  3550.     move.w    d3,d2
  3551.     lsl.l    #8,d2                ;xxaaxxxx
  3552.  IFGE    __CPU-68020
  3553.     move.w    (a1)+,d3
  3554.     move.w    (a3,d3.l*2),d3
  3555.  ELSE
  3556.     moveq    #0,d3
  3557.     move.w    (a1)+,d3
  3558.      add.w    d3,d3
  3559.      move.w    (a3,d3.l),d3
  3560.  ENDC
  3561.     move.b    d3,d1
  3562.     lsl.l    #8,d1                ;xxAABBxx
  3563.     move.w    d3,d2
  3564.     lsl.l    #8,d2                ;aabbxxxx
  3565.  IFGE    __CPU-68020
  3566.     move.w    (a1)+,d3
  3567.     move.w    (a3,d3.l*2),d3
  3568.  ELSE
  3569.     moveq    #0,d3
  3570.     move.w    (a1)+,d3
  3571.      add.w    d3,d3
  3572.      move.w    (a3,d3.l),d3
  3573.  ENDC
  3574.     move.b    d3,d1
  3575.     lsl.l    #8,d1                ;AABBCCxx
  3576.     move.w    d3,d2                ;aabbccxx
  3577.  
  3578.  IFGE    __CPU-68020
  3579.     move.w    (a1)+,d3
  3580.     move.w    (a3,d3.l*2),d3
  3581.  ELSE
  3582.     moveq    #0,d3
  3583.     move.w    (a1)+,d3
  3584.      add.w    d3,d3
  3585.      move.w    (a3,d3.l),d3
  3586.  ENDC
  3587.     move.b    d3,d1                ;AABBCCDD
  3588.     lsr.w    #8,d3
  3589.     move.b    d3,d2                ;aabbccdd
  3590.  
  3591.     move.l    d1,(a5)+
  3592.     move.l    d2,(a0)+
  3593.  
  3594.     dbf    d0,.loop
  3595.     move.l    a0,d2                ;save buffer ptr
  3596.     move.l    a5,d5                ;save buffer ptr
  3597.  
  3598.     CONVERT_POST
  3599.  
  3600.     lsr.l    #1,d0
  3601.     move.w    d0,AUD0LEN(a0)
  3602.     move.w    d0,AUD1LEN(a0)
  3603.     move.w    d0,AUD2LEN(a0)
  3604.     move.w    d0,AUD3LEN(a0)
  3605.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3606.     rts
  3607.  
  3608. *******************************************************************************
  3609.  
  3610. SoftInt_14CbitMH:
  3611.     CONVERT_PRE
  3612.  
  3613.     move.l    d2,a0                ;get buffer ptr
  3614.     move.l    d5,a5                ;get buffer ptr
  3615.     move.l    p_CalibrationTable(a6),a3
  3616.     moveq    #0,d3
  3617. .loop
  3618.  
  3619.  IFGE    __CPU-68020
  3620.     move.w    (a1),d3
  3621.     move.w    (a3,d3.l*2),d3
  3622.  ELSE
  3623.     moveq    #0,d3
  3624.     move.w    (a1),d3
  3625.      add.w    d3,d3
  3626.      move.w    (a3,d3.l),d3
  3627.  ENDC
  3628.     move.b    d3,d1
  3629.     lsl.l    #8,d1                ;xxxxAAxx
  3630.     move.w    d3,d2
  3631.     lsl.l    #8,d2                ;xxaaxxxx
  3632.  IFGE    __CPU-68020
  3633.     move.w    4(a1),d3
  3634.     move.w    (a3,d3.l*2),d3
  3635.  ELSE
  3636.     moveq    #0,d3
  3637.     move.w    4(a1),d3
  3638.      add.w    d3,d3
  3639.      move.w    (a3,d3.l),d3
  3640.  ENDC
  3641.     move.b    d3,d1
  3642.     lsl.l    #8,d1                ;xxAABBxx
  3643.     move.w    d3,d2
  3644.     lsl.l    #8,d2                ;aabbxxxx
  3645.  IFGE    __CPU-68020
  3646.     move.w    8(a1),d3
  3647.     move.w    (a3,d3.l*2),d3
  3648.  ELSE
  3649.     moveq    #0,d3
  3650.     move.w    8(a1),d3
  3651.      add.w    d3,d3
  3652.      move.w    (a3,d3.l),d3
  3653.  ENDC
  3654.     move.b    d3,d1
  3655.     lsl.l    #8,d1                ;AABBCCxx
  3656.     move.w    d3,d2                ;aabbccxx
  3657.  
  3658.  IFGE    __CPU-68020
  3659.     move.w    12(a1),d3
  3660.     move.w    (a3,d3.l*2),d3
  3661.  ELSE
  3662.     moveq    #0,d3
  3663.     move.w    12(a1),d3
  3664.      add.w    d3,d3
  3665.      move.w    (a3,d3.l),d3
  3666.  ENDC
  3667.     move.b    d3,d1                ;AABBCCDD
  3668.     lsr.w    #8,d3
  3669.     move.b    d3,d2                ;aabbccdd
  3670.  
  3671.     move.l    d1,(a5)+
  3672.     add.w    #16,a1
  3673.     move.l    d2,(a0)+
  3674.  
  3675.     dbf    d0,.loop
  3676.     move.l    a0,d2                ;save buffer ptr
  3677.     move.l    a5,d5                ;save buffer ptr
  3678.  
  3679.     CONVERT_POST
  3680.  
  3681.     lsr.l    #1,d0
  3682.     move.w    d0,AUD0LEN(a0)
  3683.     move.w    d0,AUD1LEN(a0)
  3684.     move.w    d0,AUD2LEN(a0)
  3685.     move.w    d0,AUD3LEN(a0)
  3686.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3687.     rts
  3688.  
  3689.  
  3690. *******************************************************************************
  3691.  
  3692. SoftInt_14bitS:
  3693.     CONVERT_PRE
  3694.  
  3695.     move.l    d2,a0                ;get buffer ptr
  3696.     move.l    d3,a3                ;get buffer ptr
  3697.     move.l    d4,a4                ;get buffer ptr
  3698.     move.l    d5,a5                ;get buffer ptr
  3699. .loop
  3700.  
  3701. ; Left High
  3702.     move.b    (a1),d1
  3703.     lsl.l    #8,d1
  3704.     move.b    4(a1),d1
  3705.     lsl.l    #8,d1
  3706.     move.b    8(a1),d1
  3707.     lsl.l    #8,d1
  3708.     move.b    12(a1),d1
  3709.     move.l    d1,(a3)+
  3710.  
  3711. ; Left Low
  3712.     move.b    1(a1),d1
  3713.     lsr.b    #2,d1
  3714.     lsl.l    #8,d1
  3715.     move.b    5(a1),d1
  3716.     lsr.b    #2,d1
  3717.     lsl.l    #8,d1
  3718.     move.b    9(a1),d1
  3719.     lsr.b    #2,d1
  3720.     lsl.l    #8,d1
  3721.     move.b    13(a1),d1
  3722.     lsr.b    #2,d1
  3723.     move.l    d1,(a4)+
  3724.  
  3725. ; Right High
  3726.     move.b    2(a1),d1
  3727.     lsl.l    #8,d1
  3728.     move.b    6(a1),d1
  3729.     lsl.l    #8,d1
  3730.     move.b    10(a1),d1
  3731.     lsl.l    #8,d1
  3732.     move.b    14(a1),d1
  3733.     move.l    d1,(a0)+
  3734.  
  3735. ; Right Low
  3736.     move.b    3(a1),d1
  3737.     lsr.b    #2,d1
  3738.     lsl.l    #8,d1
  3739.     move.b    7(a1),d1
  3740.     lsr.b    #2,d1
  3741.     lsl.l    #8,d1
  3742.     move.b    11(a1),d1
  3743.     lsr.b    #2,d1
  3744.     lsl.l    #8,d1
  3745.     move.b    15(a1),d1
  3746.     lsr.b    #2,d1
  3747.     move.l    d1,(a5)+
  3748.  
  3749.     add.w    #16,a1
  3750.     dbf    d0,.loop
  3751.     move.l    a0,d2                ;save buffer ptr
  3752.     move.l    a3,d3                ;save buffer ptr
  3753.     move.l    a4,d4                ;save buffer ptr
  3754.     move.l    a5,d5                ;save buffer ptr
  3755.  
  3756.     CONVERT_POST
  3757.  
  3758.     lsr.l    #1,d0
  3759.     move.w    d0,AUD0LEN(a0)
  3760.     move.w    d0,AUD1LEN(a0)
  3761.     move.w    d0,AUD2LEN(a0)
  3762.     move.w    d0,AUD3LEN(a0)
  3763.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3764.     rts
  3765.  
  3766. *******************************************************************************
  3767.  
  3768. SoftInt_14bitSH:
  3769.     CONVERT_PRE
  3770.  
  3771.     move.l    d2,a0                ;get buffer ptr
  3772.     move.l    d3,a3                ;get buffer ptr
  3773.     move.l    d4,a4                ;get buffer ptr
  3774.     move.l    d5,a5                ;get buffer ptr
  3775. .loop
  3776.  
  3777. ; Left High
  3778.     move.b    (a1),d1
  3779.     lsl.l    #8,d1
  3780.     move.b    8(a1),d1
  3781.     lsl.l    #8,d1
  3782.     move.b    16(a1),d1
  3783.     lsl.l    #8,d1
  3784.     move.b    24(a1),d1
  3785.     move.l    d1,(a3)+
  3786.  
  3787. ; Left Low
  3788.     move.b    1(a1),d1
  3789.     lsr.b    #2,d1
  3790.     lsl.l    #8,d1
  3791.     move.b    9(a1),d1
  3792.     lsr.b    #2,d1
  3793.     lsl.l    #8,d1
  3794.     move.b    17(a1),d1
  3795.     lsr.b    #2,d1
  3796.     lsl.l    #8,d1
  3797.     move.b    25(a1),d1
  3798.     lsr.b    #2,d1
  3799.     move.l    d1,(a4)+
  3800.  
  3801. ; Right High
  3802.     move.b    4(a1),d1
  3803.     lsl.l    #8,d1
  3804.     move.b    12(a1),d1
  3805.     lsl.l    #8,d1
  3806.     move.b    20(a1),d1
  3807.     lsl.l    #8,d1
  3808.     move.b    28(a1),d1
  3809.     move.l    d1,(a0)+
  3810.  
  3811. ; Right Low
  3812.     move.b    5(a1),d1
  3813.     lsr.b    #2,d1
  3814.     lsl.l    #8,d1
  3815.     move.b    13(a1),d1
  3816.     lsr.b    #2,d1
  3817.     lsl.l    #8,d1
  3818.     move.b    21(a1),d1
  3819.     lsr.b    #2,d1
  3820.     lsl.l    #8,d1
  3821.     move.b    29(a1),d1
  3822.     lsr.b    #2,d1
  3823.     move.l    d1,(a5)+
  3824.  
  3825.     add.w    #32,a1
  3826.     dbf    d0,.loop
  3827.     move.l    a0,d2                ;save buffer ptr
  3828.     move.l    a3,d3                ;save buffer ptr
  3829.     move.l    a4,d4                ;save buffer ptr
  3830.     move.l    a5,d5                ;save buffer ptr
  3831.  
  3832.     CONVERT_POST
  3833.  
  3834.     lsr.l    #1,d0
  3835.     move.w    d0,AUD0LEN(a0)
  3836.     move.w    d0,AUD1LEN(a0)
  3837.     move.w    d0,AUD2LEN(a0)
  3838.     move.w    d0,AUD3LEN(a0)
  3839.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3840.     rts
  3841.  
  3842.  
  3843. *******************************************************************************
  3844.  
  3845. SoftInt_14CbitS:
  3846.     CONVERT_PRE
  3847.  
  3848.     move.l    d2,a0                ;get buffer ptr
  3849.     move.l    d3,a3                ;get buffer ptr
  3850.     move.l    d4,a4                ;get buffer ptr
  3851.     move.l    d5,a5                ;get buffer ptr
  3852.     push    a6
  3853.     move.l    p_CalibrationTable(a6),a6
  3854.     moveq    #0,d3
  3855. .loop
  3856.  
  3857. ; Left
  3858.  IFGE    __CPU-68020
  3859.     move.w    (a1),d3
  3860.     move.w    (a6,d3.l*2),d3
  3861.  ELSE
  3862.     moveq    #0,d3
  3863.     move.w    (a1),d3
  3864.      add.w    d3,d3
  3865.      move.w    (a6,d3.l),d3
  3866.  ENDC
  3867.     move.b    d3,d1
  3868.     lsl.l    #8,d1                ;xxxxAAxx
  3869.     move.w    d3,d2
  3870.     lsl.l    #8,d2                ;xxaaxxxx
  3871.  IFGE    __CPU-68020
  3872.     move.w    4(a1),d3
  3873.     move.w    (a6,d3.l*2),d3
  3874.  ELSE
  3875.     moveq    #0,d3
  3876.     move.w    4(a1),d3
  3877.      add.w    d3,d3
  3878.      move.w    (a6,d3.l),d3
  3879.  ENDC
  3880.     move.b    d3,d1
  3881.     lsl.l    #8,d1                ;xxAABBxx
  3882.     move.w    d3,d2
  3883.     lsl.l    #8,d2                ;aabbxxxx
  3884.  IFGE    __CPU-68020
  3885.     move.w    8(a1),d3
  3886.     move.w    (a6,d3.l*2),d3
  3887.  ELSE
  3888.     moveq    #0,d3
  3889.     move.w    8(a1),d3
  3890.      add.w    d3,d3
  3891.      move.w    (a6,d3.l),d3
  3892.  ENDC
  3893.     move.b    d3,d1
  3894.     lsl.l    #8,d1                ;AABBCCxx
  3895.     move.w    d3,d2                ;aabbccxx
  3896.  
  3897.  IFGE    __CPU-68020
  3898.     move.w    12(a1),d3
  3899.     move.w    (a6,d3.l*2),d3
  3900.  ELSE
  3901.     moveq    #0,d3
  3902.     move.w    12(a1),d3
  3903.      add.w    d3,d3
  3904.      move.w    (a6,d3.l),d3
  3905.  ENDC
  3906.     move.b    d3,d1                ;AABBCCDD
  3907.     lsr.w    #8,d3
  3908.     move.b    d3,d2                ;aabbccdd
  3909.  
  3910.     move.l    d1,(a4)+
  3911.     move.l    d2,(a3)+
  3912.  
  3913. ; Right
  3914.  IFGE    __CPU-68020
  3915.     move.w    2(a1),d3
  3916.     move.w    (a6,d3.l*2),d3
  3917.  ELSE
  3918.     moveq    #0,d3
  3919.     move.w    2(a1),d3
  3920.      add.w    d3,d3
  3921.      move.w    (a6,d3.l),d3
  3922.  ENDC
  3923.     move.b    d3,d1
  3924.     lsl.l    #8,d1                ;xxxxAAxx
  3925.     move.w    d3,d2
  3926.     lsl.l    #8,d2                ;xxaaxxxx
  3927.  IFGE    __CPU-68020
  3928.     move.w    6(a1),d3
  3929.     move.w    (a6,d3.l*2),d3
  3930.  ELSE
  3931.     moveq    #0,d3
  3932.     move.w    6(a1),d3
  3933.      add.w    d3,d3
  3934.      move.w    (a6,d3.l),d3
  3935.  ENDC
  3936.     move.b    d3,d1
  3937.     lsl.l    #8,d1                ;xxAABBxx
  3938.     move.w    d3,d2
  3939.     lsl.l    #8,d2                ;aabbxxxx
  3940.  IFGE    __CPU-68020
  3941.     move.w    10(a1),d3
  3942.     move.w    (a6,d3.l*2),d3
  3943.  ELSE
  3944.     moveq    #0,d3
  3945.     move.w    10(a1),d3
  3946.      add.w    d3,d3
  3947.      move.w    (a6,d3.l),d3
  3948.  ENDC
  3949.     move.b    d3,d1
  3950.     lsl.l    #8,d1                ;AABBCCxx
  3951.     move.w    d3,d2                ;aabbccxx
  3952.  
  3953.  IFGE    __CPU-68020
  3954.     move.w    14(a1),d3
  3955.     move.w    (a6,d3.l*2),d3
  3956.  ELSE
  3957.     moveq    #0,d3
  3958.     move.w    14(a1),d3
  3959.      add.w    d3,d3
  3960.      move.w    (a6,d3.l),d3
  3961.  ENDC
  3962.     move.b    d3,d1                ;AABBCCDD
  3963.     lsr.w    #8,d3
  3964.     move.b    d3,d2                ;aabbccdd
  3965.  
  3966.     move.l    d1,(a5)+
  3967.     add.w    #16,a1
  3968.     move.l    d2,(a0)+
  3969.  
  3970.     dbf    d0,.loop
  3971.     pop    a6
  3972.     move.l    a0,d2                ;save buffer ptr
  3973.     move.l    a3,d3                ;save buffer ptr
  3974.     move.l    a4,d4                ;save buffer ptr
  3975.     move.l    a5,d5                ;save buffer ptr
  3976.  
  3977.     CONVERT_POST
  3978.  
  3979.     lsr.l    #1,d0
  3980.     move.w    d0,AUD0LEN(a0)
  3981.     move.w    d0,AUD1LEN(a0)
  3982.     move.w    d0,AUD2LEN(a0)
  3983.     move.w    d0,AUD3LEN(a0)
  3984.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3985.     rts
  3986.  
  3987.  
  3988. *******************************************************************************
  3989.  
  3990. SoftInt_14CbitSH:
  3991.     CONVERT_PRE
  3992.  
  3993.     move.l    d2,a0                ;get buffer ptr
  3994.     move.l    d3,a3                ;get buffer ptr
  3995.     move.l    d4,a4                ;get buffer ptr
  3996.     move.l    d5,a5                ;get buffer ptr
  3997.     push    a6
  3998.     move.l    p_CalibrationTable(a6),a6
  3999.     moveq    #0,d3
  4000. .loop
  4001.  
  4002. ; Left
  4003.  IFGE    __CPU-68020
  4004.     move.w    (a1),d3
  4005.     move.w    (a6,d3.l*2),d3
  4006.  ELSE
  4007.     moveq    #0,d3
  4008.     move.w    (a1),d3
  4009.      add.w    d3,d3
  4010.      move.w    (a6,d3.l),d3
  4011.  ENDC
  4012.     move.b    d3,d1
  4013.     lsl.l    #8,d1                ;xxxxAAxx
  4014.     move.w    d3,d2
  4015.     lsl.l    #8,d2                ;xxaaxxxx
  4016.  IFGE    __CPU-68020
  4017.     move.w    8(a1),d3
  4018.     move.w    (a6,d3.l*2),d3
  4019.  ELSE
  4020.     moveq    #0,d3
  4021.     move.w    8(a1),d3
  4022.      add.w    d3,d3
  4023.      move.w    (a6,d3.l),d3
  4024.  ENDC
  4025.     move.b    d3,d1
  4026.     lsl.l    #8,d1                ;xxAABBxx
  4027.     move.w    d3,d2
  4028.     lsl.l    #8,d2                ;aabbxxxx
  4029.  IFGE    __CPU-68020
  4030.     move.w    16(a1),d3
  4031.     move.w    (a6,d3.l*2),d3
  4032.  ELSE
  4033.     moveq    #0,d3
  4034.     move.w    16(a1),d3
  4035.      add.w    d3,d3
  4036.      move.w    (a6,d3.l),d3
  4037.  ENDC
  4038.     move.b    d3,d1
  4039.     lsl.l    #8,d1                ;AABBCCxx
  4040.     move.w    d3,d2                ;aabbccxx
  4041.  
  4042.  IFGE    __CPU-68020
  4043.     move.w    24(a1),d3
  4044.     move.w    (a6,d3.l*2),d3
  4045.  ELSE
  4046.     moveq    #0,d3
  4047.     move.w    24(a1),d3
  4048.      add.w    d3,d3
  4049.      move.w    (a6,d3.l),d3
  4050.  ENDC
  4051.     move.b    d3,d1                ;AABBCCDD
  4052.     lsr.w    #8,d3
  4053.     move.b    d3,d2                ;aabbccdd
  4054.  
  4055.     move.l    d1,(a4)+
  4056.     move.l    d2,(a3)+
  4057.  
  4058. ; Right
  4059.  IFGE    __CPU-68020
  4060.     move.w    4(a1),d3
  4061.     move.w    (a6,d3.l*2),d3
  4062.  ELSE
  4063.     moveq    #0,d3
  4064.     move.w    4(a1),d3
  4065.      add.w    d3,d3
  4066.      move.w    (a6,d3.l),d3
  4067.  ENDC
  4068.     move.b    d3,d1
  4069.     lsl.l    #8,d1                ;xxxxAAxx
  4070.     move.w    d3,d2
  4071.     lsl.l    #8,d2                ;xxaaxxxx
  4072.  IFGE    __CPU-68020
  4073.     move.w    12(a1),d3
  4074.     move.w    (a6,d3.l*2),d3
  4075.  ELSE
  4076.     moveq    #0,d3
  4077.     move.w    12(a1),d3
  4078.      add.w    d3,d3
  4079.      move.w    (a6,d3.l),d3
  4080.  ENDC
  4081.     move.b    d3,d1
  4082.     lsl.l    #8,d1                ;xxAABBxx
  4083.     move.w    d3,d2
  4084.     lsl.l    #8,d2                ;aabbxxxx
  4085.  IFGE    __CPU-68020
  4086.     move.w    20(a1),d3
  4087.     move.w    (a6,d3.l*2),d3
  4088.  ELSE
  4089.     moveq    #0,d3
  4090.     move.w    20(a1),d3
  4091.      add.w    d3,d3
  4092.      move.w    (a6,d3.l),d3
  4093.  ENDC
  4094.     move.b    d3,d1
  4095.     lsl.l    #8,d1                ;AABBCCxx
  4096.     move.w    d3,d2                ;aabbccxx
  4097.  
  4098.  IFGE    __CPU-68020
  4099.     move.w    28(a1),d3
  4100.     move.w    (a6,d3.l*2),d3
  4101.  ELSE
  4102.     moveq    #0,d3
  4103.     move.w    28(a1),d3
  4104.      add.w    d3,d3
  4105.      move.w    (a6,d3.l),d3
  4106.  ENDC
  4107.     move.b    d3,d1                ;AABBCCDD
  4108.     lsr.w    #8,d3
  4109.     move.b    d3,d2                ;aabbccdd
  4110.  
  4111.     move.l    d1,(a5)+
  4112.     add.w    #32,a1
  4113.     move.l    d2,(a0)+
  4114.  
  4115.     dbf    d0,.loop
  4116.     pop    a6
  4117.     move.l    a0,d2                ;save buffer ptr
  4118.     move.l    a3,d3                ;save buffer ptr
  4119.     move.l    a4,d4                ;save buffer ptr
  4120.     move.l    a5,d5                ;save buffer ptr
  4121.  
  4122.     CONVERT_POST
  4123.  
  4124.     lsr.l    #1,d0
  4125.     move.w    d0,AUD0LEN(a0)
  4126.     move.w    d0,AUD1LEN(a0)
  4127.     move.w    d0,AUD2LEN(a0)
  4128.     move.w    d0,AUD3LEN(a0)
  4129.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  4130.     rts
  4131.  
  4132.  
  4133.  
  4134.  
  4135.  
  4136.  
  4137.  
  4138. *******************************************************************************
  4139. ***** DMA playback routines ***************************************************
  4140. *******************************************************************************
  4141.  
  4142. ;in:
  4143. * a2    AudioCtrl
  4144. * a3    paula
  4145. * a4    custom
  4146. * a5    paulaBase
  4147. * a6    ExecBase
  4148. ; out:
  4149. * d0    AHIsub_Start return code
  4150.  
  4151. DMA_Start:
  4152.     PRINTF    2,"DMA_Start()"
  4153.  
  4154. * Allocate DMA buffers
  4155.     move.l    #DMABUFFSAMPLES*8,d0            ; 4 channels, double buffers
  4156.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  4157.     call    AllocVec
  4158.     move.l    d0,p_DMAbuffer(a3)
  4159.     beq    .nomem
  4160.  
  4161.     move.l    #DMABUFFSAMPLES,d1
  4162.     move.l    d0,p_AudPtr1A(a3)
  4163.     add.l    d1,d0
  4164.     move.l    d0,p_AudPtr1B(a3)
  4165.     add.l    d1,d0
  4166.     move.l    d0,p_AudPtr2A(a3)
  4167.     add.l    d1,d0
  4168.     move.l    d0,p_AudPtr2B(a3)
  4169.     add.l    d1,d0
  4170.     move.l    d0,p_AudPtr3A(a3)
  4171.     add.l    d1,d0
  4172.     move.l    d0,p_AudPtr3B(a3)
  4173.     add.l    d1,d0
  4174.     move.l    d0,p_AudPtr4A(a3)
  4175.     add.l    d1,d0
  4176.     move.l    d0,p_AudPtr4B(a3)
  4177.  
  4178. * Set up audio hardware interrupts
  4179.     move.l    #AudioInterruptDMA,IS_CODE+p_PlayInt(a3)
  4180.     move.l    a3,IS_DATA+p_PlayInt(a3)
  4181.  
  4182.     lea    p_PlayInt(a3),a1
  4183.     moveq    #INTB_AUD0,d0
  4184.     call    SetIntVector
  4185.     lea    p_PlayInt(a3),a1
  4186.     moveq    #INTB_AUD1,d0
  4187.     call    SetIntVector
  4188.     lea    p_PlayInt(a3),a1
  4189.     moveq    #INTB_AUD2,d0
  4190.     call    SetIntVector
  4191.     lea    p_PlayInt(a3),a1
  4192.     moveq    #INTB_AUD3,d0
  4193.     call    SetIntVector
  4194.  
  4195.     clr.w    p_DisableCount(a3)
  4196.  
  4197. * Use timer.device to clock the PlayerFunc() using a software interrupt/msg port
  4198.  
  4199.     lea    p_TimerPort+MP_MSGLIST(a3),a0
  4200.     NEWLIST    a0
  4201.  
  4202.     lea    p_TimerPort(a3),a0
  4203.     move.b    #NT_MSGPORT,LN_TYPE(a0)
  4204.     move.b    #PA_SOFTINT,MP_FLAGS(a0)
  4205.     lea    p_TimerInt(a3),a1
  4206.     move.l    a1,MP_SIGTASK(a0)
  4207.     
  4208.     move.b    #32,p_TimerInt+LN_PRI(a3)    ; Highest priority to keep it steady
  4209.     lea    PlayerFunc(pc),a0
  4210.     move.l    a0,p_TimerInt+IS_CODE(a3)
  4211.     move.l    a3,p_TimerInt+IS_DATA(a3)
  4212.  
  4213.     lea    p_TimerPort(a3),a0
  4214.     moveq    #IOTV_SIZE,d0
  4215.     call    CreateIORequest
  4216.     move.l    d0,p_TimerReq(a3)
  4217.     beq    .notimer
  4218.  
  4219.     lea    timerName(pc),a0
  4220.     moveq    #UNIT_ECLOCK,d0
  4221.     move.l    p_TimerReq(a3),a1
  4222.     moveq    #0,d0
  4223.     call    OpenDevice
  4224.     move.b    d0,p_TimerDev(a3)
  4225.     bne    .notimer
  4226.  
  4227.     move.l    p_TimerReq(a3),a0
  4228.     move.l    IO_DEVICE(a0),pb_TimerLib(a5)
  4229.  
  4230.     move.l    a5,a6
  4231.     bsr    DMA_Update                ;Calc p_EClock/p_EPeriod
  4232.                             ;and p_EAlarm
  4233.     ; Add p_EPeriod to the alarm time
  4234.     move.l    p_EAlarm+EV_LO(a3),d0
  4235.     move.l    p_EAlarm+EV_HI(a3),d1
  4236.     move.l    p_EPeriod(a3),d2
  4237.     moveq    #0,d3
  4238.     add.l    d0,d2
  4239.     addx.l    d1,d3
  4240.     move.l    d2,p_EAlarm+EV_LO(a3)
  4241.     move.l    d3,p_EAlarm+EV_HI(a3)
  4242.  
  4243.     clr.w    p_TimerCommFlag(a3)
  4244.  
  4245.     move.l    p_TimerReq(a3),a1
  4246.     move.w    #TR_ADDREQUEST,IO_COMMAND(a1)
  4247.     move.l    p_EPeriod(a3),IOTV_TIME+EV_LO(a1)
  4248.     clr.l    IOTV_TIME+EV_HI(a1)
  4249.     bsr    BeginIO
  4250.  
  4251.     or.w    #INTF_SETCLR|INTF_AUDIO,p_IRQMask(a3)
  4252.     move.w    #INTF_SETCLR|INTF_AUDIO,INTENA(a4)    ;enable all
  4253.     move.w    #INTF_SETCLR|INTF_AUDIO,INTREQ(a4)    ;start all
  4254.  
  4255.     moveq    #AHIE_OK,d0
  4256. .exit
  4257.     rts
  4258.  
  4259. .notimer
  4260.     moveq    #AHIE_UNKNOWN,d0
  4261.     bra    .exit
  4262.  
  4263. .nomem
  4264.     moveq    #AHIE_NOMEM,d0
  4265.     bra    .exit
  4266.  
  4267.  
  4268. ;in:
  4269. * a2    AudioCtrl
  4270. * a3    paula
  4271. * a6    paulaBase
  4272.  
  4273. DMA_Update:
  4274.     PRINTF    2,"DMA_Update()"
  4275.     move.l    pb_TimerLib(a6),d0
  4276.     beq    .error
  4277.     push    a6
  4278.     move.l    d0,a6
  4279.     lea    p_EAlarm(a3),a0
  4280.     call    ReadEClock
  4281.     move.l    d0,p_EClock(a3)
  4282.     pop    a6
  4283.  
  4284.     lsl.l    #8,d0
  4285.     move.l    ahiac_PlayerFreq(a2),d1
  4286.     lsr.l    #8,d1
  4287.     beq    .error
  4288.  
  4289.  IFGE    __CPU-68020
  4290.     divu.l    d1,d0
  4291.  ELSE
  4292.     move.l    pb_UtilLib(a6),a0
  4293.     jsr    _LVOUDivMod32(a0)
  4294.  ENDIF
  4295.     move.l    d0,p_EPeriod(a3)
  4296. .exit
  4297.     rts
  4298.  
  4299. .error
  4300.     move.l    #709379/50,p_EPeriod(a3)    ;Approx 50 Hz
  4301.     bra    .exit
  4302.     
  4303.  
  4304. ;in:
  4305. * a2    AudioCtrl
  4306. * a3    paula
  4307. * a4    custom
  4308. * a5    paulaBase
  4309. * a6    ExecBase
  4310.  
  4311. DMA_Stop:
  4312.     PRINTF    2,"DMA_Stop()"
  4313.  
  4314.     and.w    #INTF_AUDIO,p_IRQMask(a3)
  4315.     move.w    #INTF_AUDIO,INTENA(a4)
  4316.     move.w    #DMAF_AUDIO,DMACON(a4)        ;Disable DMA
  4317.     move.w    #INTF_AUDIO,INTREQ(a4)        ;Clear any waiting interrupts
  4318.  
  4319.     tst.b    p_TimerDev(a3)
  4320.     bne    .notimer
  4321.  
  4322. * Ask timer softint to stop
  4323.  
  4324.     addq.w    #1,p_TimerCommFlag(a3)
  4325. .waittimer
  4326.     tst.w    p_TimerCommFlag(a3)
  4327.     beq    .closetimer
  4328.     move.l    pb_DosLib(a5),a6
  4329.     moveq    #1,d1
  4330.     call    Delay
  4331.     bra    .waittimer
  4332. .closetimer
  4333.  
  4334.     move.b    #-1,p_TimerDev(a3)
  4335.     clr.l    pb_TimerLib(a5)
  4336.  
  4337.     move.l    pb_SysLib(a5),a6
  4338.     move.l    p_TimerReq(a3),a0
  4339.     call    CloseDevice
  4340. .notimer
  4341.     move.l    p_TimerReq(a3),a0
  4342.     clr.l    p_TimerReq(a3)
  4343.     call    DeleteIORequest
  4344.  
  4345.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  4346.  
  4347.     lea    p_PlayInt(a3),a1
  4348.     moveq    #INTB_AUD0,d0
  4349.     call    SetIntVector
  4350.     lea    p_PlayInt(a3),a1
  4351.     moveq    #INTB_AUD1,d0
  4352.     call    SetIntVector
  4353.     lea    p_PlayInt(a3),a1
  4354.     moveq    #INTB_AUD2,d0
  4355.     call    SetIntVector
  4356.     lea    p_PlayInt(a3),a1
  4357.     moveq    #INTB_AUD3,d0
  4358.     call    SetIntVector
  4359.  
  4360.     move.l    p_DMAbuffer(a3),a1
  4361.     clr.l    p_DMAbuffer(a3)
  4362.     call    FreeVec
  4363.  
  4364.     rts
  4365.  
  4366.  
  4367. ****** [driver].audio/AHIsub_#? *********************************************
  4368. *
  4369. *   NAME
  4370. *       AHIsub_SetEffect -- Set effect.
  4371. *       AHIsub_SetFreq -- Set frequency.
  4372. *       AHIsub_SetSound -- Set sound.
  4373. *       AHIsub_SetVol -- Set volume and stereo panning.
  4374. *       AHIsub_LoadSound -- Prepare a sound for playback.
  4375. *       AHIsub_UnloadSound -- Discard a sound.
  4376. *
  4377. *   SYNOPSIS
  4378. *       See functions in 'ahi.device'.
  4379. *
  4380. *   IMPLEMENTATION
  4381. *       If AHIsub_AllocAudio() did not return with bit AHISB_MIXING set,
  4382. *       all user calls to these function will be routed to the driver.
  4383. *
  4384. *       If AHIsub_AllocAudio() did return with bit AHISB_MIXING set, the
  4385. *       calls will first be routed to the driver, and only handled by
  4386. *       'ahi.device' if the driver returned AHIS_UNKNOWN. This way it is
  4387. *       possible to add effects that the sound card handles on its own, like
  4388. *       filter and echo effects.
  4389. *
  4390. *       For what each function does, see the autodocs for 'ahi.device'.
  4391. *
  4392. *   INPUTS
  4393. *       See functions in 'ahi.device'.
  4394. *
  4395. *   NOTES
  4396. *       See functions in 'ahi.device'.
  4397. *
  4398. *   SEE ALSO
  4399. *       ahi.device/AHI_SetEffect(), ahi.device/AHI_SetFreq(),
  4400. *       ahi.device/AHI_SetSound(), ahi.device/AHI_SetVol(),
  4401. *       ahi.device/AHI_LoadSound(), ahi.device/AHI_UnloadSound()
  4402. *       
  4403. *
  4404. *****************************************************************************
  4405. *
  4406. *
  4407.  
  4408.  
  4409. *****************************************************************************
  4410. * Panning is ignored, and negative volume is not supported.
  4411.  
  4412. AHIsub_SetVol:
  4413.     push    a3
  4414.     move.l    ahiac_DriverData(a2),a3
  4415.     btst.b    #PB_DMA,p_Flags(a3)
  4416.     beq    AHIsub_NoDMA
  4417.  
  4418.     PRINTF    2,"AHIsub_SetVol()"
  4419.     mulu.w    #channel_SIZEOF,d0
  4420.     lea    p_Channels(a3),a0
  4421.     add.l    d0,a0
  4422.     asr.l    #8,d1
  4423.     asr.w    #2,d1
  4424.     bpl    .plus
  4425.     neg.w    d1
  4426. .plus
  4427.     bsr    AHIsub_Disable
  4428.  
  4429. * Store volume and scale according to the master volume
  4430.     move.w    d1,ch_NextVolumeNorm(a0)
  4431.     move.l    p_MasterVolume(a3),d0
  4432.     cmp.l    #$10000,d0
  4433.     blo    .scale1
  4434.     move.w    d1,d0
  4435.     bra    .store1
  4436. .scale1
  4437.     mulu.w    d1,d0
  4438.     swap.w    d0
  4439. .store1
  4440.     move.w    d0,ch_NextVolume(a0)
  4441.  
  4442.     btst    #AHISB_IMM,d3
  4443.     beq    .noimm
  4444.     move.w    d1,ch_VolumeNorm(a0)
  4445.     move.l    p_MasterVolume(a3),d0
  4446.     cmp.l    #$10000,d0
  4447.     blo    .scale2
  4448.     move.w    d1,d0
  4449.     bra    .store2
  4450. .scale2
  4451.     mulu.w    d1,d0
  4452.     swap.w    d0
  4453. .store2
  4454.     move.w    d0,ch_Volume(a0)
  4455. ;    move.l    ch_PerVol(a0),ch_AudPerVol(a0)
  4456.     move.l    ch_RegBase(a0),a1
  4457.     move.w    d0,AUDVOL(a1)
  4458. .noimm
  4459.  
  4460.     bsr    AHIsub_Enable
  4461.  
  4462.     moveq    #0,d0                ; Return NULL!
  4463.  
  4464.     pop    a3
  4465.     rts
  4466.  
  4467. *****************************************************************************
  4468. * If the frequency is higher than the audio DMA can handle, the samples will
  4469. * be decimated before they are played. The frequency will only take effect
  4470. * immediately if the decimate factor didn't change, or the new frequency
  4471. * was zero. Otherwise, the frequency will change when the current DMA
  4472. * block is finished.
  4473.  
  4474. AHIsub_SetFreq:
  4475.     push    a3
  4476.     move.l    ahiac_DriverData(a2),a3
  4477.     btst.b    #PB_DMA,p_Flags(a3)
  4478.     beq    AHIsub_NoDMA
  4479.  
  4480.     PRINTF    2,"AHIsub_SetFreq()"
  4481.     push    d3
  4482.     mulu.w    #channel_SIZEOF,d0
  4483.     lea    p_Channels(a3),a0
  4484.     add.l    d0,a0
  4485.  
  4486.     cmp.l    #AHI_MIXFREQ,d1
  4487.     bne    .normal_freq
  4488.     move.l    ahiac_MixFreq(a2),d1
  4489. .normal_freq
  4490.  
  4491.     move.l    #28800,d0
  4492.     tst.w    p_ScreenIsDouble(a3)
  4493.     beq    .1
  4494.     move.l    #48000,d0
  4495. .1
  4496.     moveq    #0,d3            ; Decimate/scale (log)
  4497. .loop
  4498.     cmp.l    d0,d1
  4499.     bls    .scaled
  4500.     addq.l    #1,d3
  4501.     lsr.l    #1,d1
  4502.     bra    .loop
  4503. .scaled
  4504.  
  4505.     tst.l    d1
  4506.     bne    .notnull
  4507.     moveq    #0,d0            ;VVVeeerrryyyy ssslllooowww!!!
  4508.     moveq    #0,d3
  4509.     bra    .gotperiod
  4510. .notnull
  4511.  
  4512.     move.l    p_AudioFreq(a3),d0
  4513.  
  4514.  IFGE    __CPU-68020
  4515.     divu.l    d1,d0
  4516.  ELSE
  4517.     move.l    pb_UtilLib(a6),a1
  4518.     jsr    _LVOUDivMod32(a1)
  4519.  ENDIF
  4520.  
  4521. .gotperiod
  4522.  
  4523.     bsr    AHIsub_Disable
  4524.  
  4525.     move.w    d0,ch_NextPeriod(a0)
  4526.     move.w    d3,ch_NextScale(a0)
  4527.  
  4528.     btst    #AHISB_IMM,d2
  4529.     beq    .noimm
  4530.  
  4531. ; We must not change the frequency if the scale has changed! (Unless it's 0)
  4532.     tst.w    d3
  4533.     beq    .change
  4534.     cmp.w    ch_Scale(a0),d3
  4535.     bne    .nochange
  4536. .change
  4537. ;    move.l    ch_PerVol(a0),ch_AudPerVol(a0)
  4538.     move.l    ch_RegBase(a0),a1
  4539.     move.w    d0,AUDPER(a1)
  4540. .nochange
  4541.  
  4542.     ; Force an interrupt if the channel was paused
  4543.     tst.w    ch_Period(a0)
  4544.     bne    .notzero
  4545.     tst.b    ch_NoInt(a0)
  4546.     bne    .noint
  4547.     lea    custom,a1
  4548.     move.w    ch_IntMask(a0),d1
  4549.     or.w    #INTF_SETCLR,d1
  4550.     move.w    d1,INTREQ(a1)
  4551. .noint
  4552. .notzero
  4553.  
  4554.     move.w    d0,ch_Period(a0)
  4555.     move.w    d3,ch_Scale(a0)
  4556.  
  4557. .noimm
  4558.  
  4559.     bsr    AHIsub_Enable
  4560.  
  4561.     moveq    #0,d0                ; Return NULL!
  4562.     pop    d3
  4563.  
  4564.     pop    a3
  4565.     rts
  4566.  
  4567. *****************************************************************************
  4568.  
  4569. AHIsub_SetSound:
  4570.     push    a3
  4571.     move.l    ahiac_DriverData(a2),a3
  4572.     btst.b    #PB_DMA,p_Flags(a3)
  4573.     beq    AHIsub_NoDMA
  4574.  
  4575.     PRINTF    2,"AHIsub_SetSound()"
  4576.     pushm    d2-d5
  4577.  
  4578.     mulu.w    #channel_SIZEOF,d0
  4579.     lea    p_Channels(a3),a0
  4580.     add.l    d0,a0
  4581.  
  4582.     cmp.w    #AHI_NOSOUND,d1
  4583.     bne    .sound_ok
  4584.     moveq    #0,d2
  4585.     moveq    #0,d3
  4586.     moveq    #AHIST_NOTYPE,d5
  4587.     bra    .update_channel
  4588. .sound_ok
  4589.  
  4590.     mulu.w    #sound_SIZEOF,d1
  4591.     move.l    p_Sounds(a3),a1
  4592.     add.l    d1,a1
  4593.  
  4594.     tst.l    d3
  4595.     bne    .length_ok
  4596.     move.l    so_Length(a1),d3
  4597. .length_ok
  4598.     move.l    so_Type(a1),d5
  4599.  
  4600. .update_channel
  4601.  
  4602.     tst.l    d3
  4603.     bpl    .positive_length
  4604.     neg.l    d3                ; Make positive
  4605.     or.l    #AHIST_BW,d5            ; Mark type as backward-playing
  4606. .positive_length
  4607.  
  4608. ;    PRINTF    0,"New sample! %08lx, %ld, %08lx", d2,d3,d5
  4609.  
  4610.     bsr    AHIsub_Disable
  4611.  
  4612.     move.l    so_Address(a1),ch_NextAddress(a0)
  4613.     move.l    d2,ch_NextOffset(a0)
  4614.     move.l    d3,ch_NextLength(a0)
  4615.     move.l    d5,ch_NextType(a0)
  4616.  
  4617.  
  4618.     btst    #AHISB_IMM,d4
  4619.     beq    .noimm
  4620.  
  4621.     move.l    so_Address(a1),ch_Address(a0)
  4622.     move.l    d2,ch_Offset(a0)
  4623.     move.l    d3,ch_Length(a0)
  4624.     move.l    d5,ch_Type(a0)
  4625.     clr.l    ch_Count(a0)
  4626.     st.b    ch_EndOfSample(a0)        ; Call SoundFunc()
  4627.  
  4628.     lea    custom,a1
  4629.  
  4630. ; Clear pending interrupt (if there was one)
  4631.     st.b    ch_NoInt(a0)
  4632.     move.w    ch_IntMask(a0),INTREQ(a1)
  4633.  
  4634. ; Stop this channel
  4635.     move.w    ch_DMAMask(a0),DMACON(a1)
  4636.  
  4637.     ; Wait for Agnus/Alice to understand
  4638.     push    a6
  4639.     move.l    pb_SysLib(a6),a6
  4640.     call    Disable
  4641.  
  4642.     move.b    VHPOSR(a1),d0
  4643. .vert
  4644.     cmp.b    VHPOSR(a1),d0
  4645.     beq    .vert
  4646. .hori
  4647.     cmp.b    #20,VHPOSR+1(a1)
  4648.     blt    .hori
  4649.  
  4650.     call    Enable
  4651.     pop    a6
  4652.  
  4653. ; When the period reaches 0, Paula will invoke our interrupt routine!
  4654.  
  4655. ; Now just make sure that we receive no more than 1 interrupt.
  4656.     move.l    ch_RegBase(a0),a1
  4657.     move.w    #1,AUDPER(a1)
  4658. .noimm
  4659.  
  4660.     bsr    AHIsub_Enable
  4661.  
  4662.     moveq    #0,d0                ; Return NULL!
  4663.     popm    d2-d5
  4664.  
  4665.     pop    a3
  4666.     rts
  4667.  
  4668. *****************************************************************************
  4669.  
  4670. AHIsub_SetEffect:
  4671.     push    a3
  4672.     move.l    ahiac_DriverData(a2),a3
  4673.     btst.b    #PB_DMA,p_Flags(a3)
  4674.     beq    AHIsub_NoDMA
  4675.  
  4676.     PRINTF    2,"AHIsub_SetEffect()"
  4677.     move.l    ahie_Effect(a0),d0
  4678.     cmp.l    #AHIET_MASTERVOLUME,d0
  4679.     beq    .mastervolume
  4680.     cmp.l    #AHIET_CANCEL|AHIET_MASTERVOLUME,d0
  4681.     beq    .mastervolume_off
  4682.     cmp.l    #AHIET_CHANNELINFO,d0
  4683.     beq    .channelinfo
  4684.     cmp.l    #AHIET_CANCEL|AHIET_CHANNELINFO,d0
  4685.     beq    .channelinfo_off
  4686.  
  4687.     moveq    #AHIE_UNKNOWN,d0        ; Return error code!
  4688. .exit
  4689.     pop    a3
  4690.     rts
  4691.  
  4692. .mastervolume
  4693.     move.l    ahiemv_Volume(a0),d0
  4694. .mastervolume_update
  4695.     move.l    d0,p_MasterVolume(a3)
  4696.  
  4697.     lea    p_Channels(a3),a0
  4698.     moveq    #3,d1
  4699. .mastervolume_loop
  4700.     move.l    p_MasterVolume(a3),d0
  4701.     cmp.l    #$10000,d0
  4702.     blo    .mastervolume_scale1
  4703.     move.w    ch_NextVolumeNorm(a0),d0
  4704.     bra    .mastervolume_store1
  4705. .mastervolume_scale1
  4706.     mulu.w    ch_NextVolumeNorm(a0),d0
  4707.     swap.w    d0
  4708. .mastervolume_store1
  4709.     move.w    d0,ch_NextVolume(a0)
  4710.     move.l    p_MasterVolume(a3),d0
  4711.     cmp.l    #$10000,d0
  4712.     blo    .mastervolume_scale2
  4713.     move.w    ch_VolumeNorm(a0),d0
  4714.     bra    .mastervolume_store2
  4715. .mastervolume_scale2
  4716.     mulu.w    ch_VolumeNorm(a0),d0
  4717.     swap.w    d0
  4718. .mastervolume_store2
  4719.     move.w    d0,ch_Volume(a0)
  4720. ;    move.l    ch_PerVol(a0),ch_AudPerVol(a0)
  4721.     move.l    ch_RegBase(a0),a1
  4722.     move.w    d0,AUDVOL(a1)
  4723.  
  4724.     add.w    #channel_SIZEOF,a0
  4725.     dbf    d1,.mastervolume_loop
  4726.  
  4727.     moveq    #AHIE_OK,d0
  4728.     bra    .exit
  4729.  
  4730. .mastervolume_off
  4731.     move.l    #$10000,d0
  4732.     bra    .mastervolume_update
  4733.  
  4734.  
  4735. .channelinfo
  4736.     move.l    a0,p_ChannelInfo(a3)
  4737.     moveq    #AHIE_OK,d0
  4738.     bra    .exit
  4739.  
  4740. .channelinfo_off
  4741.     clr.l    p_ChannelInfo(a3)
  4742.     moveq    #AHIE_OK,d0
  4743.     bra    .exit
  4744.  
  4745.  
  4746. *****************************************************************************
  4747.  
  4748. AHIsub_LoadSound:
  4749.     push    a3
  4750.     move.l    ahiac_DriverData(a2),a3
  4751.     btst.b    #PB_DMA,p_Flags(a3)
  4752.     beq    AHIsub_NoDMA
  4753.  
  4754.     PRINTF    2,"AHIsub_LoadSound()"
  4755.     cmp.l    #AHIST_SAMPLE,d1
  4756.     beq    .soundok
  4757.     cmp.l    #AHIST_DYNAMICSAMPLE,d1
  4758.     bne    .unknownsound
  4759. .soundok
  4760.     mulu.w    #sound_SIZEOF,d0
  4761.     move.l    p_Sounds(a3),a1
  4762.     add.l    d0,a1
  4763.  
  4764.     move.l    ahisi_Type(a0),d0
  4765.     cmp.l    #AHIST_M8S,d0
  4766.     beq    .sampleok
  4767.     cmp.l    #AHIST_M16S,d0
  4768.     beq    .sampleok
  4769.     cmp.l    #AHIST_S8S,d0
  4770.     beq    .sampleok
  4771.     cmp.l    #AHIST_S16S,d0
  4772.     bne    .unknownsample
  4773. .sampleok
  4774.     move.l    d0,so_Type(a1)
  4775.     move.l    ahisi_Address(a0),so_Address(a1)
  4776.     move.l    ahisi_Length(a0),so_Length(a1)
  4777.  
  4778.     moveq    #AHIE_OK,d0
  4779. .exit
  4780.  
  4781.     pop    a3
  4782.     rts
  4783.  
  4784. .unknownsound
  4785.     moveq    #AHIE_BADSOUNDTYPE,d0
  4786.     bra    .exit
  4787. .unknownsample
  4788.     moveq    #AHIE_BADSAMPLETYPE,d0
  4789.     bra    .exit
  4790.  
  4791. *****************************************************************************
  4792.  
  4793. AHIsub_UnloadSound:
  4794.     push    a3
  4795.     move.l    ahiac_DriverData(a2),a3
  4796.     btst.b    #PB_DMA,p_Flags(a3)
  4797.     beq    AHIsub_NoDMA
  4798.  
  4799.     PRINTF    2,"AHIsub_UnloadSound()"
  4800.     mulu.w    #sound_SIZEOF,d0
  4801.     move.l    p_Sounds(a3),a1
  4802.     add.l    d0,a1
  4803.     move.l    #AHIST_NOTYPE,so_Type(a1)
  4804.     clr.l    so_Address(a1)
  4805.     clr.l    so_Length(a1)
  4806.  
  4807.     moveq    #0,d0                ; Return NULL!
  4808.  
  4809.     pop    a3
  4810.     rts
  4811.  
  4812. *****************************************************************************
  4813.  
  4814. AHIsub_NoDMA:
  4815.     moveq    #AHIS_UNKNOWN,d0        ; Return AHIS_UNKNOWN!
  4816.     pop    a3
  4817.     rts
  4818.  
  4819. *****************************************************************************
  4820.  
  4821. ;in:
  4822. * a1    struct paula *
  4823.  
  4824. PlayerFunc:
  4825.     pushm    std
  4826.  
  4827.     move.l    a1,a3
  4828.     move.l    p_AudioCtrl(a3),a2
  4829.  
  4830.     move.l    4.w,a6
  4831.     lea    p_TimerPort(a3),a0
  4832.     call    GetMsg                ; Remove message
  4833.  
  4834.     tst.w    p_TimerCommFlag(a3)
  4835.     beq    .normal
  4836.  
  4837.     clr.w    p_TimerCommFlag(a3)
  4838.     bra    .exit
  4839.  
  4840. .normal
  4841.     ; Add p_EPeriod to the alarm time
  4842.     move.l    p_EAlarm+EV_LO(a3),d0
  4843.     move.l    p_EAlarm+EV_HI(a3),d1
  4844.     move.l    p_EPeriod(a3),d2
  4845.     moveq    #0,d3
  4846.     add.l    d0,d2
  4847.     addx.l    d1,d3
  4848.     move.l    d2,p_EAlarm+EV_LO(a3)
  4849.     move.l    d3,p_EAlarm+EV_HI(a3)
  4850.  
  4851.     ; Get current time
  4852.     push    a6
  4853.     move.l    p_PaulaBase(a3),a0
  4854.     move.l    pb_TimerLib(a0),a6
  4855.     subq.l    #8,sp
  4856.     move.l    sp,a0
  4857.     call    ReadEClock
  4858.     move.l    EV_LO(sp),d0            ; Current time
  4859.     move.l    EV_HI(sp),d1
  4860.     sub.l    d0,d2                ; Calculate difference (Alarm - Current)
  4861.     subx.l    d1,d3
  4862.     addq.l    #8,sp
  4863.     pop    a6
  4864.  
  4865.     tst.l    d3
  4866.     bpl    .positive
  4867.     moveq    #1,d2
  4868.     moveq    #0,d3                ; Rather small delay...
  4869. .positive
  4870.  
  4871. ;    PRINTF    0,"Delay: %08ld%08ld",d3,d2
  4872.     move.l    p_TimerReq(a3),a1
  4873.     move.w    #TR_ADDREQUEST,IO_COMMAND(a1)
  4874.     move.l    d2,IOTV_TIME+EV_LO(a1)
  4875.     move.l    d3,IOTV_TIME+EV_HI(a1)
  4876.     bsr    BeginIO
  4877.  
  4878.     bsr    AHIsub_Disable
  4879.  
  4880.     ; Handle the ChannelInfo effect
  4881.  
  4882.     move.l    p_ChannelInfo(a3),d0
  4883.     beq    .nochannelinfo
  4884.     move.l    d0,a0
  4885.     lea    ahieci_Offset(a0),a1
  4886.     move.w    ahieci_Channels(a0),d0
  4887.     subq.w    #1,d0
  4888.     bmi    .nochannelinfo
  4889.     lea    p_Channels(a3),a4
  4890. .loop
  4891.     move.l    ch_Offset(a4),(a1)+
  4892.     add.w    #channel_SIZEOF,a4
  4893.     dbf    d0,.loop
  4894.  
  4895.     move.l    p_ChannelInfo(a3),a1
  4896.     move.l    ahieci_Func(a1),d0
  4897.     beq    .nochannelinfo
  4898.     move.l    d0,a0
  4899.     move.l    h_Entry(a0),a4
  4900.     jsr    (a4)
  4901.  
  4902. ;    lea    p_Channels(a3),a4
  4903. ;    PRINTF    0,"CI: %ld, %ld, %ld, %ld",ch_Offset(a4),ch_Offset+channel_SIZEOF(a4),ch_Offset+channel_SIZEOF*2(a4),ch_Offset+channel_SIZEOF*3(a4)
  4904. .nochannelinfo
  4905.  
  4906.     ; Call the PlayerFunc()
  4907.  
  4908.     move.l    ahiac_PlayerFunc(a2),d0
  4909.     move.l    d0,a0
  4910.     beq    .noplayerfunc
  4911.     sub.l    a1,a1                ; IMPORTANT!
  4912.     move.l    h_Entry(a0),a4
  4913.     PRINTF    8,"Calling PlayerFunc(%08lx,%08lx,%08lx)",a0,a2,a1
  4914.     jsr    (a4)
  4915. .noplayerfunc
  4916.  
  4917.     bsr    AHIsub_Enable
  4918.  
  4919. .exit
  4920.     moveq    #0,d0
  4921.     popm    std
  4922.     rts
  4923.  
  4924. *****************************************************************************
  4925.  
  4926. ;in:
  4927. * d0    scratch
  4928. * d1.w    INTENAR & INTREQR
  4929. * a0    custom
  4930. * a1    struct paula *
  4931. * a5    &AudioInterruptDMA
  4932. * a6    ExecBase
  4933.  
  4934. AudioInterruptDMA:
  4935.     pushm    std
  4936.  
  4937.     PRINTF    3,"."
  4938.     PRINTF    6,"AudioInterruptDMA"
  4939.  
  4940.     move.l    p_AudioCtrl(a1),a4
  4941.     lea    p_Channels(a1),a5
  4942.     lea    p_AudPtr1A(a1),a6
  4943.     move.w    d1,d7
  4944.  
  4945.     move.w    ch_IntMask(a5),d0
  4946.     and.w    d7,d0
  4947.     beq    .not0
  4948.  
  4949.     move.l    ch_RegBase(a5),a0
  4950.     move.l    ch_PerVol(a5),AUDPERVOL(a0)
  4951. ;    move.l    ch_AudPerVol(a5),AUDPERVOL(a0)
  4952. ;    move.l    ch_PerVol(a5),ch_AudPerVol(a5)
  4953.  
  4954.     bsr    DMA_HandleInt
  4955.  
  4956.     move.w    ch_IntMask(a5),custom+INTREQ        ; Clear the interrupt
  4957.     move.l    ch_RegBase(a5),a0
  4958.     move.l    (a6),AUDLC(a0)
  4959.     move.w    ch_DMALength(a5),AUDLEN(a0)
  4960.  
  4961.     clr.b    ch_NoInt(a5)
  4962. .not0
  4963.  
  4964.     add.w    #channel_SIZEOF,a5
  4965.     addq.l    #8,a6
  4966.  
  4967.     move.w    ch_IntMask(a5),d0
  4968.     and.w    d7,d0
  4969.     beq    .not1
  4970.  
  4971.     move.l    ch_RegBase(a5),a0
  4972.     move.l    ch_PerVol(a5),AUDPERVOL(a0)
  4973. ;    move.l    ch_AudPerVol(a5),AUDPERVOL(a0)
  4974. ;    move.l    ch_PerVol(a5),ch_AudPerVol(a5)
  4975.  
  4976.     bsr    DMA_HandleInt
  4977.  
  4978.     move.w    ch_IntMask(a5),custom+INTREQ        ; Clear the interrupt
  4979.     move.l    ch_RegBase(a5),a0
  4980.     move.l    (a6),AUDLC(a0)
  4981.     move.w    ch_DMALength(a5),AUDLEN(a0)
  4982.  
  4983.     clr.b    ch_NoInt(a5)
  4984. .not1
  4985.  
  4986.     add.w    #channel_SIZEOF,a5
  4987.     addq.l    #8,a6
  4988.  
  4989.     move.w    ch_IntMask(a5),d0
  4990.     and.w    d7,d0
  4991.     beq    .not2
  4992.  
  4993.     move.l    ch_RegBase(a5),a0
  4994.     move.l    ch_PerVol(a5),AUDPERVOL(a0)
  4995. ;    move.l    ch_AudPerVol(a5),AUDPERVOL(a0)
  4996. ;    move.l    ch_PerVol(a5),ch_AudPerVol(a5)
  4997.  
  4998.     bsr    DMA_HandleInt
  4999.  
  5000.     move.w    ch_IntMask(a5),custom+INTREQ        ; Clear the interrupt
  5001.     move.l    ch_RegBase(a5),a0
  5002.     move.l    (a6),AUDLC(a0)
  5003.     move.w    ch_DMALength(a5),AUDLEN(a0)
  5004.  
  5005.     clr.b    ch_NoInt(a5)
  5006. .not2
  5007.  
  5008.     add.w    #channel_SIZEOF,a5
  5009.     addq.l    #8,a6
  5010.  
  5011.     move.w    ch_IntMask(a5),d0
  5012.     and.w    d7,d0
  5013.     beq    .not3
  5014.  
  5015.     move.l    ch_RegBase(a5),a0
  5016.     move.l    ch_PerVol(a5),AUDPERVOL(a0)
  5017. ;    move.l    ch_AudPerVol(a5),AUDPERVOL(a0)
  5018. ;    move.l    ch_PerVol(a5),ch_AudPerVol(a5)
  5019.  
  5020.     bsr    DMA_HandleInt
  5021.  
  5022.     move.w    ch_IntMask(a5),custom+INTREQ        ; Clear the interrupt
  5023.     move.l    ch_RegBase(a5),a0
  5024.     move.l    (a6),AUDLC(a0)
  5025.     move.w    ch_DMALength(a5),AUDLEN(a0)
  5026.  
  5027.     clr.b    ch_NoInt(a5)
  5028. .not3
  5029.  
  5030. .exit
  5031.     lea    custom,a0
  5032.     move.w    #DMAF_SETCLR|DMAF_AUDIO,DMACON(a0)    ; Enable DMA
  5033. ;    move.w    #INTF_AUDIO,INTREQ(a0)            ; Clear the interrupts
  5034.  
  5035.     popm    std
  5036.     rts
  5037. * d0-d6 scratch
  5038. * a0-a3 scratch
  5039. * a4    AHIAudioCtrlDrv
  5040. * a5    struct channel *
  5041. * a6    BYTE **buffer[2]
  5042. DMA_HandleInt:
  5043.  
  5044. * Check if the next set of parameters should be fetced
  5045.  
  5046.     cmp.l    #AHIST_NOTYPE,ch_Type(a5)
  5047.     beq    .check_eos
  5048.     tst.b    ch_EndOfSample(a5)            ; Already set?
  5049.     bne    .check_eos
  5050.     move.l    ch_Count(a5),d0
  5051.     beq    .check_eos
  5052.     move.l    ch_Length(a5),d1
  5053.     and.l    #~1,d1                    ; Force even
  5054.     cmp.l    d1,d0
  5055.     blo    .check_eos
  5056.  
  5057. .load_next
  5058.     move.l    ch_NextAddress(a5),ch_Address(a5)
  5059.     move.l    ch_NextLength(a5),ch_Length(a5)
  5060.     move.l    ch_NextType(a5),ch_Type(a5)
  5061.     move.l    ch_NextPerVol(a5),ch_PerVol(a5)
  5062.     move.w    ch_NextScale(a5),ch_Scale(a5)
  5063.     move.l    ch_NextOffset(a5),ch_Offset(a5)
  5064.     clr.l    ch_Count(a5)
  5065.  
  5066.     PRINTF    4,"New sound! %08lx, Length: %ld, Type: %08lx, PerVol: %08lx",ch_Address(a5),ch_Length(a5),ch_Type(a5),ch_PerVol(a5)
  5067.  
  5068.     ; Signal that SoundFunc() should be called
  5069.     st.b    ch_EndOfSample(a5)
  5070.  
  5071.  
  5072. * Check if SoundFunc() should be called
  5073. .check_eos
  5074.     tst.b    ch_EndOfSample(a5)
  5075.     beq    .not_eos
  5076.     clr.b    ch_EndOfSample(a5)            ; Clear signal
  5077.  
  5078.     ; Call the SoundFunc()
  5079.     move.l    ahiac_SoundFunc(a4),d0
  5080.     move.l    d0,a0
  5081.     beq    .nosoundfunc
  5082.     lea    ch_SndMsg(a5),a1
  5083.     move.l    a4,a2
  5084.     move.l    h_Entry(a0),a3
  5085.     moveq    #0,d0
  5086.     move.w    ahism_Channel(a1),d0
  5087.     PRINTF    4,"Calling SoundFunc(%08lx,%08lx,%ld)",a0,a2,d0
  5088.     jsr    (a3)
  5089. .nosoundfunc
  5090. .not_eos
  5091.  
  5092. * Swap chipmem buffers
  5093.     move.l    4(a6),a1
  5094.     move.l    (a6),4(a6)
  5095.     move.l    a1,(a6)
  5096. * Swap cleared indicators
  5097.     move.l    ch_Cleared2(a5),d0
  5098.     move.l    ch_Cleared(a5),ch_Cleared2(a5)
  5099.     move.l    d0,ch_Cleared(a5)
  5100.  
  5101.     move.l    ch_Address(a5),a2
  5102.     moveq    #0,d2
  5103.     move.w    ch_Scale(a5),d2
  5104.  
  5105.     move.l    ch_Length(a5),d0
  5106.     move.l    ch_Count(a5),d1
  5107.  
  5108. * Calculate the number of samples to transfer (this is source samples, which is
  5109. * a multiple of the destination samples if ch_Scale != 0.
  5110.  
  5111.     sub.l    d1,d0
  5112.     ble    .endofsample            ; <= 0 ?
  5113.     tst.w    ch_Period(a5)
  5114.     bne    .normallength
  5115. .endofsample
  5116. * We have either already reached the end of the sample, or it's paused.
  5117. * Set the length to DMABUFFSAMPLES and scale to 0. (I.e., clear the whole
  5118. * chipmem buffer.) Do NOT increase ch_Offset/ch_Count!
  5119.     move.l    #DMABUFFSAMPLES,d0
  5120.     moveq    #0,d2
  5121.     bra    .set_dmalength
  5122. .normallength
  5123.  
  5124.     ; samples = max(samples, DMABUFFSAMPLES*(2^scale))
  5125.     move.l    #DMABUFFSAMPLES,d3
  5126.     lsl.l    d2,d3
  5127.     cmp.l    d3,d0
  5128.     blo    .1
  5129.     move.l    d3,d0
  5130. .1
  5131.     add.l    d0,ch_Count(a5)
  5132.  
  5133. * Get current ch_Offset
  5134.     move.l    ch_Offset(a5),d1
  5135.  
  5136. * Update the ch_Offset
  5137.     move.l    ch_Type(a5),d3
  5138.     and.l    #AHIST_BW,d3
  5139.     beq    .2
  5140.     sub.l    d0,ch_Offset(a5)
  5141.     skipl
  5142. .2
  5143.     add.l    d0,ch_Offset(a5)
  5144.  
  5145. .set_dmalength
  5146.     lsr.l    d2,d0                ; Calc. destination samples
  5147.     move.l    d0,d3
  5148.     lsr.l    #1,d3                ; # of words, round to lower
  5149.     move.w    d3,ch_DMALength(a5)
  5150.  
  5151.     move.l    d2,d3                ;Convert ²log scale...
  5152.     moveq    #0,d2
  5153.     bset    d3,d2                ;...to linear
  5154.  
  5155.     move.l    ch_Type(a5),d3
  5156.  
  5157. * If the period is 0, this sample is paused => clear the buffer
  5158. * If type == AHIST_NOTYPE, clear the buffer
  5159.     tst.w    ch_Period(a5)
  5160.     beq    .clearsample
  5161.     cmp.l    #AHIST_NOTYPE,d3
  5162.     bne    .istype
  5163.  
  5164. .clearsample
  5165.  
  5166. * Alright, we should play silence. But before the dma buffer is filled with
  5167. * zeroes, check if we already have cleared it. In that case, there is no need
  5168. * to do that again (chipmem accesses are expensive!).
  5169.     cmp.l    ch_Cleared(a5),d0
  5170.     bls    .filled                ; Skip it!
  5171.     move.l    d0,ch_Cleared(a5)
  5172.     lea    ClearSample(pc),a3
  5173.     bra    .fill
  5174. .istype
  5175.  
  5176. * It was a normal sample. Figure out which transfer routine to use etc.
  5177.     clr.l    ch_Cleared(a5)            ; Mark buffer as un-cleared
  5178.     move.l    d3,d4
  5179.     and.l    #AHIST_BW,d4
  5180.     beq    .forwardsample
  5181.     neg.l    d2
  5182. .forwardsample
  5183.     and.l    #~AHIST_BW,d3            ; Mask fwd/bwd bit
  5184.     cmp.l    #AHIST_S16S,d3
  5185.     bhi    .error                ; Sanity check!
  5186.     lsl.l    #2,d3
  5187.     move.l    .jmp(pc,d3.l),a3
  5188. .fill
  5189.     jsr    (a3)
  5190. .filled
  5191. .exit
  5192.     rts
  5193.  
  5194. * This should never happen...
  5195. .error
  5196.     PRINTF    2,"Illegal type! %08lx",d3
  5197.     bra    .exit
  5198.  
  5199. .jmp
  5200.     dc.l    CopySampleM8S
  5201.     dc.l    CopySampleM16S
  5202.     dc.l    CopySampleS8S
  5203.     dc.l    CopySampleS16S
  5204.  
  5205. ;in:
  5206. * d0    Samples to copy
  5207. * d1    Source offset
  5208. * d2    Decimate/Scale (not log, but linear, can be negative)
  5209. * a1    Destination
  5210. * a2    Source
  5211. * a5    Channel
  5212.  
  5213. ClearSample:
  5214.     PRINTF    6,"ClearSample %08lx, %ld, %ld",a1,d0,d1
  5215.     addq.l    #3,d0
  5216.     lsr.l    #2,d0                ;Unrolled
  5217.     subq.l    #1,d0
  5218.     bmi    .exit
  5219. .loop
  5220.     clr.l    (a1)+
  5221.     dbf    d0,.loop
  5222. .exit
  5223.     rts
  5224.  
  5225.  
  5226. CopySampleM8S:
  5227.     PRINTF    6,"CopySampleM8S %08lx, %ld, %ld",a1,d0,d1
  5228.     addq.l    #3,d0
  5229.     lsr.l    #2,d0                ;Unrolled
  5230.     subq.l    #1,d0
  5231.     bmi    CopySampleExit
  5232.     add.l    d1,a2
  5233.     cmp.w    #0,a2
  5234.     bne    CopySample
  5235.     bra    CopySampleError
  5236.  
  5237. CopySampleM16S:
  5238.     PRINTF    6,"CopySampleM16S %08lx, %ld, %ld",a1,d0,d1
  5239.     lsl.l    #1,d1                ; 16 bits/sample
  5240.     lsl.l    #1,d2                ; 16 bits/sample
  5241.     addq.l    #3,d0
  5242.     lsr.l    #2,d0                ;Unrolled
  5243.     subq.l    #1,d0
  5244.     bmi    CopySampleExit
  5245.     add.l    d1,a2
  5246.     cmp.w    #0,a2
  5247.     bne    CopySample
  5248.     bra    CopySampleError
  5249.  
  5250. CopySampleS8S:
  5251.     PRINTF    6,"CopySampleS8S %08lx, %ld, %ld",a1,d0,d1
  5252.     lsl.l    #1,d1                ; 16 bits/sample frame
  5253.     lsl.l    #1,d2                ; 16 bits/sample frame
  5254.     addq.l    #3,d0
  5255.     lsr.l    #2,d0                ;Unrolled
  5256.     subq.l    #1,d0
  5257.     bmi    CopySampleExit
  5258.     add.l    d1,a2
  5259.     cmp.w    #0,a2
  5260.     beq    CopySampleError
  5261.     add.w    ch_Stereo(a5),a2
  5262.     bra    CopySample
  5263.  
  5264. CopySampleS16S:
  5265.     PRINTF    6,"CopySampleS16S %08lx, %ld, %ld",a1,d0,d1
  5266.     lsl.l    #2,d1                ; 32 bits/sample frame
  5267.     lsl.l    #2,d2                ; 32 bits/sample frame
  5268.     addq.l    #3,d0
  5269.     lsr.l    #2,d0                ;Unrolled
  5270.     subq.l    #1,d0
  5271.     bmi    CopySampleExit
  5272.     add.l    d1,a2
  5273.     cmp.w    #0,a2
  5274.     beq    CopySampleError
  5275.     add.w    ch_Stereo(a5),a2
  5276.     add.w    ch_Stereo(a5),a2
  5277.     bra    CopySample
  5278.  
  5279. CopySampleExit:
  5280.     rts
  5281.  
  5282. CopySampleError
  5283.     PRINTF    2,"CopySampleError"
  5284.     bra    CopySampleExit
  5285.  
  5286. * Collect 4 samples and write a full longword to the chipmem buffer
  5287. CopySample:
  5288. .loop
  5289.     move.b    (a2),d3
  5290.     add.l    d2,a2
  5291.     lsl.l    #8,d3
  5292.     move.b    (a2),d3
  5293.     add.l    d2,a2
  5294.     lsl.l    #8,d3
  5295.     move.b    (a2),d3
  5296.     add.l    d2,a2
  5297.     lsl.l    #8,d3
  5298.     move.b    (a2),d3
  5299.     add.l    d2,a2
  5300.     move.l    d3,(a1)+
  5301.     dbf    d0,.loop
  5302.     rts
  5303. EndCode:
  5304.